2.3 MapReduce工作流程
整个MapReduce的重点
Map阶段
- 步骤1,已有数据,在`/user/input下
- 步骤2,该节点主要是将解析出的key/value交给用户编写map()函数处理,并产生一系列新的key/value
其实就是切片
- 步骤3,提交信息:
切片信息、xml、jar
- 步骤4,由YARN调用Resourcemanager
【Yarn RM】
,Yarn RM
创建Mr appmaster【一个job资源协调的老大;分配整个集群任务的调度和协调】
,Mr appmaster
根据步骤3中的job.split切片信息
决定启动多少个MapTask; - 步骤5,启动MapTask后读取信息,用什么读:默认TextInputFormat
一行一行读
,或可通过改变RecorderReader修改读法可自定义改为读一个文件
; - 步骤6,在读完一行后,将数据返回给Mapper,处理相应的业务逻辑
数据转换、封装等
;最后Context.write(k,v)写出
- Collect收集阶段:在用户编写map()函数中,当数据处理完成后,一般会调用OutputCollector.collect()输出结果。在该函数内部,它会将生成的key/value分区(调用Partitioner),并写入一个环形内存缓冲区中。
- 步骤7,将写出的数据,写出到(内存中的)环形缓冲区
outputCollector,大小为100M,分两侧:右侧写数据,左侧写索引【标记数据的长度、位置等信息】
;当写到80%时,要溢写【将内存中数据写入到磁盘】内存要放不下了
;就是个队列 - 步骤8,当环形缓冲区的数据达到80%或已经读完后,进行分区,分区内排序
按key字典顺序排序;快排算法
; - 步骤9,溢写:序列化到磁盘
可能溢写多次;不仅存数据还存索引信息
- 步骤10,对9中的部分有序数据,进行归并排序
Merge
,形成大的有序 - 步骤11,合并
可选择阶段
:combiner,在拿到Map阶段数据后,先进行合并,减少数据的输出,起到优化作用,是reduce阶段接到较少数据。当所有数据处理完成后,MapTask对所有临时文件进行一次合并,以确保最终只会生成一个数据文件
- 步骤12,完成MapTask任务后,根据
数据分区的数量
,启动相应的ReduceTask;默认是1个,也可自行设置;分区数是1,reduceTask是1,不执行分区过程,执行分区的前提是判断个数是否大于1
- 步骤13,是一个拷贝过程;
MapTask1和MapTask2各有两个分区,启动2个ReduceTask,ReduceTask1处理MapTask1分区0的数据和MapTask2中分区0的数据;ReduceTask2处理MapTask1分区1的数据和MapTask2中分区1的数据
; - 步骤13,将拷贝来的小有序归并排序
合并
为大有序文件 - 步骤14,将合并文件,一次读一组,按k值相同读到同一个Reduce(k,v)中
- 步骤15,分组OrderGroupingComparator
分组排序;比如:使同类商品输出价格最高的
,得到reduce数据后先分组,为了使相同的key进入到同一个Reducer(k,v)方法。 - 步骤16,以io流方式向外写
上面的流程是整个MapReduce最全工作流程
但是Shuffle
过程Map之后,Reduce之前
只是从第7步开始到第16步结束,具体Shuffle过程详解,如下:
1)MapTask收集我们的map()方法输出的kv对,放到内存缓冲区中
2)从内存缓冲区不断溢出本地磁盘文件,可能会溢出多个文件
3)多个溢出文件会被合并成大的溢出文件
4)在溢出过程及合并的过程中,都要调用Partitioner进行分区和针对key进行排序
5)ReduceTask根据自己的分区号,去各个MapTask机器上取相应的结果分区数据
6)ReduceTask会取到同一个分区的来自不同MapTask的结果文件,ReduceTask会将这些文件再进行合并(归并排序)
7)合并成大文件后,Shuffle的过程也就结束了,后面进入ReduceTask的逻辑运算过程(从文件中取出一个一个的键值对Group,调用用户自定义的reduce()方法)