Hadoop学习笔记-MapReduce(5)-MapTask和ReduceTask
MapTask
Read阶段:MapTask通过InputFormat获得RecordReader,从输入中解析出一个个键值对
Map阶段:将得到的键值对交给用户编写的map函数进行处理,并产生一系列新的键值对
Collect阶段:将生成的键值对进行分区(调用Partitioner),并写入一个环形缓冲区内
Spill阶段:溢写阶段。溢写阶段会生成临时文件,在数据写入本地磁盘之前,先对数据进行一次本地排序,并在必要的时候对数据进行合并、压缩等操作
- 使用快排:先按照分区编号进行排序,然后按照key进行排序。这样经过排序之后,数据以分区为单位聚集在一起,并且同一分区所有的数据对key有序
- 按照分区编号由小到大将数据写入临时文件中(任务工作目录下的
output/spillN.out
)。如果用户设置了Combiner,则在写入文件之前还会对每个分区的数据进行一次合并操作 - 分区数据的元信息也会写入内存中,每个分区的元信息中包括了分区在临时文件中的偏移量,压缩前数据大小和压缩后数据大小。如果当前内存的索引超过1MB,也会将内存索引写入文件
output/spillN.out.index
中
Merge阶段:当所有数据处理完成之后,MapTask对所有的临时文件进行一次合并,以确保最终只会生成一个数据文件。
- 所有的临时文件合并成一个大文件
output/file.out
,同时生成相应的索引文件output/file.out.index
- 在进行文件合并的过程中,MapTask以分区为单位进行合并,对于某个分区来说,会采用多轮递归合并的方式。(每轮合并
mapreduce.task.io.sort.factor
默认10个文件)
让每个MapTask最终只生成一个数据文件,可以避免同时打开大量文件和同时读取大量小文件产生的随机读取带来的开销
- 所有的临时文件合并成一个大文件
ReduceTask
- Copy阶段:ReduceTask从各个MapTask上远程拷贝对应数据。并且针对某一片数据,如果其大小超过一定阈值,则写在磁盘上,否则直接放在内存当中
- Sort阶段:在远程拷贝数据的同时,ReduceTsk启动了两个后台线程对内存和磁盘上的文件进行合并,以防止内存使用过多或磁盘上的文件过多。
- Reduce阶段:用户自定义的reduce函数进行结果计算
对于ReduceTask的启动个数:
- ReduceTask = 0,表示没有Reduce阶段,输出文件个数和Map个数一致,这时候也没有Shuffle阶段
- ReduceTask默认值为1
- 如果数据分布不均匀,在Reduce阶段很有可能产生数据倾斜
- ReduceTask数量并不是任意设置的,还要考虑业务逻辑需求
- 如果分区数量不是1但是ReduceTask数量是1,则不执行分区过程。因为在MapTask的源码中,执行分区的前提是先判断ReduceNum的个数是否大于1,不大于1的话则不会执行分区过程。
Hadoop学习笔记-MapReduce(5)-MapTask和ReduceTask
http://example.com/2022/02/22/Hadoop学习笔记-MapReduce-5-MapTask和ReduceTask/