持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第7天
13.5.4.2ReduceTask源码解析流程
搜索这个,然后选择第一个
然后ctrl+f搜索isMapOrReduce这个,然后再这行打上断点,然后再继续下一步,一直到如下位置
这里一定要提前打上断点,否则抓不到这个位置
这里上来就是3个阶段,copy,sort,reduce,会走5遍,因为有5个分区,然后进行下一步操作,一直到如下位置
在此处打上断点,首先强行进入会进入到this.getJobID()里面,然后退出来,再次强行进入,到如下图
在这里打上断点,害怕跑偏,然后下一步,直到下图位置
这里是新旧API的兼容问题,使用新的API继续下一步,到如下位置
运行到Path outputPath = FileOutputFormat.getOutputPath(this.conf);这个位置,鼠标放到outputFormat这个上面,默认情况下,可以看到使用的是TextOutputFormat
然后退出来
然后一直下一步,到如下位置
在 shuffleConsumerPlugin.init(shuffleContext);和this.sortPhase.complete();这两个地方打上断点
然后强行进入这个方法,看他初始化了那些内容
进来后在此处打上断点,当他是new对象的时候要进入里面在里面打上断点,如下图
这样就是最靠谱的
然后退出来
一直下一步到红框处
点击下一步
进入到这里
这里是获取有多少个MapTask,以此ReduceTask来拉取的时候知道需要拉几个
然后退出来
这里也需要打上断点
然后走到这个位置,强行进入
在进入这个里面打断点
在这里打上断点,然后点上方返回
然后点下一步
前面是各种初始化,因为马上要拉取数据了,而数据要放在内存上,内存不够了放磁盘上,一直点下一步,到如下图位置
先准备好内存和磁盘,初始化工作做好,在进行拉取数据,然后一直点下一步就行
在这里rIter = shuffleConsumerPlugin.run();打上断点,然后强行进入
在这三处打上断点,然后一直下一步,到如下图位置
从名字上可以看出来,这步是ReduceTask从MapTask上抓取数据,然后继续下一步,到如下图位置
到这里就抓取数据完毕了,然后继续往下走,到如下图位置
copy结束,当前阶段切换成SORT阶段,然后继续往下走,到如下图位置
先在下面红框打上断点,sort结束了,当前阶段切换成REDUCE阶段,然后继续往下走,到如下图位置
到这个地方,强行进入
然后继续往下走,到如下图位置
提前在此处打上断点,强行进入
进入到这里了,这里是初始化,关闭,正常的reducer的聚合
这里要提前打断点,然后继续往下走,到如下图位置
到这里是将相同的key往外写,(这里我的例子是相同的手机号往外写总的流量),然后强行进入
强行进入
强行进入
在这里打上断点,下一步
到这里,先写的key,看他是如何写的,强行进入
给他打上断点,然后继续往下走,到如下图位置
看他是如何写的,强行进入
进来后给这行代码打上断点,然后继续往下走,到如下图位置
到这里强行进入
下一步
强行进入
下一步
强行进入
强行进入
强行进入
然后继续往下走,到如下图位置
以上key已经写完了,开始写value了,强行进入,然后继续往下走,到如下图位置
强行进入
就到了自己定义的flowBean,根据自己定义的格式往外写,然后一个key就写完了,但是MapTask里面有多个key,然后继续往下走,到如下图位置
key变成了13736230513,直到这个分区全部写出去
全速运行
就到这个地方了,开启下一个ReduceTask,结束了上一个ReduceTask。
后面就和之前步骤一样了,就不展示了
=================== ReduceTask ===================
if (isMapOrReduce()) //reduceTask324行,提前打断点
initialize() // reduceTask333行,进入
init(shuffleContext); // reduceTask375行,走到这需要先给下面的打断点
totalMaps = job.getNumMapTasks(); // ShuffleSchedulerImpl第120行,提前打断点
merger = createMergeManager(context); //合并方法,Shuffle第80行
// MergeManagerImpl第232 235行,提前打断点
this.inMemoryMerger = createInMemoryMerger(); //内存合并
this.onDiskMerger = new OnDiskMerger(this); //磁盘合并
rIter = shuffleConsumerPlugin.run();
eventFetcher.start(); //开始抓取数据,Shuffle第107行,提前打断点
eventFetcher.shutDown(); //抓取结束,Shuffle第141行,提前打断点
copyPhase.complete(); //copy阶段完成,Shuffle第151行
taskStatus.setPhase(TaskStatus.Phase.SORT); //开始排序阶段,Shuffle第152行
sortPhase.complete(); //排序阶段完成,即将进入reduce阶段 reduceTask382行
reduce(); //reduce阶段调用的就是我们自定义的reduce方法,会被调用多次
cleanup(context); //reduce完成之前,会最后调用一次Reducer里面的cleanup方法