MapReduce工作流程原理详解

(1)输入数据(Input):

客户端submit()(客户端submit()前就已经将数据进行逻辑上的规划,也就是切片了),客户端将数据信息(job.split , wc.jar等)提交给Yarn的ResourceManager进行处理,ResourceManager启动NodeManager和ApplicationMaster,ApplicationMaster根据接收到的job.split信息,开启与切片个数相同个数的MapTask,MapTask启动后,用InputFormat(默认是TextInputFormat)的RecorderReader按行读取文件,然后传给Mapper(因为Mapper的输入key是偏移量,输入value就是读取的一行内容)

(2)Mapper阶段:

接收到RecorderReader传过来的K,V后,在重写的map()方法中进行用户自定义的业务逻辑操作,然后通过context.write(outK,outV)将数据输出到OutputCollector,也叫环形缓冲区

(3)Shuffle阶段:

①环形缓冲区,分为两个部分,左边存储右边数据相对应的索引(index – 索引,partition – 分区,keystart – 标记数据存储在哪,valuestart – 标记数据存储在哪),右边存储数据(map阶段的key – 偏移量,value – 行的内容),当环形缓冲区的内存达到80%时,进行溢写到磁盘,(因为达到100%后,容易让数据等待,效率低,80%时,效率高)
②数据一进到环形缓冲区的时候,就会被标记好在哪个分区,(因为每个分区存储的位置不一样,在不同的reduce文件中,所以提前分配好,独立进行处理)然后会对分区内部的数据进行排序(等到环形缓冲区到达80%,进行溢写前,进行排序),采用快排(对索引进行排序)
③【快排之后】到达80%的时候,就会将环形缓冲区的数据溢写到磁盘文件上,然后对不同文件上(有多个MapTask任务)的数据进行(Merge)归并排序(保证每一个分区内部是有序的),排序完之后仍然还在磁盘上
④【所有排序完成以后】可以进行Combiner合并(只是一个优化手段,不是所有情况都可以用),作用就是(不写的时候传a,1 a,1)传个累加和,a,2
⑤环形缓冲区默认大小是100M,也可以改变大小(通过mapreduce.task.io.sort.mb)

(4)Reducer阶段:

通过ApplicationMaster(MrappMaster),会在所有的MapTask任务完成后(一般是等待所有的MapTask完成后,再启动,但有时任务量过大,也可以通过设置改变,只需要等待一部分MapTask完成后便会启动),启动相应数量的ReduceTask,并让ReduceTask开始工作,ReduceTask开启之后,ReduceTask主动从MapTask对应的分区拉取自己指定分区的数据,然后合并文件,进行归并排序。再将相同的key传输到reduce()方法,reduce()方法处理完之后,用context.write(outK,outV)写出

(5)输出数据(Output):

用OutputFormat(默认是TextOutputFormat)的RecordWriter写出到对应的文件part-r-000xx