MapReduce(十一): 详解Reduce任务运行

来源:互联网 发布:协同过滤算法代码 编辑:程序博客网 时间:2024/06/17 05:46

Map在处理完后会根据Reduce的个数对处理结果进行划区存储(默认情况下是根据Key的Hash进行划分,也可指定自己划分实现),在Reduce阶段根据Reduce的ID向各个Map获取属于这个Reduce分区的数据,叫做shuffle。

ReduceTask中有一个线程GetMapEventsThread.java定时向TaskTracker获取该Job的Map执行成功的事件,TaskTracker中也启动一个线程定时向JobTracker获取该TaskTracker上所有Job的Map执行成功的事件,获取到的事件供ReduceTask查询。


   获取Map事件的源代码:

   ReduceTask.GetMapEventsThread.java

 

   在GetMapEventsThread线程获取Map事件后,就由主线程调度开始由MapOutputCopier线程进行数据传输到本地,MapOutputCopier开启多个线程并行从Map获取数据,Reduce向Map是通过Http chunked方式传输数据到本地,如果数据较小则直接放到内存,内存不够用了则把数据写到文件中。InMemFSMergeThread和LocalFSMerger线程实时检查数据传输结果,当内存不够用或者文件个数超过指定阈值时就进行对多个Map的数据合并,合并的方式与Map阶段对多个文件分区进行合并一样。

   在数据拷贝完成后停止InMemFSMergeThread和LocalFSMerger线程,开始对所有分区的数据进行总的合并到一个文件并把该文件的数据写到Job指定的在hdfs上的output目录。

   

MapOutputCopier.java负责对Map的结果按照http chunked方式获取,获取的数据长度写在http头中,源代码如下:


如果传输的数据能够放在内存则直接放在缓存中,如果不够放则写到文件中:

 

每次数据写到内存中时,都要申请内存大小,如果内存不够,则等待InMemFSMergeThread线程把内存数据合并到文件中,并且把内存释放,直到内存够用

MapOutputCopier.java#shuffleInMemory


 

如果数据不够存放在内存中,则直接写到本地文件中:

MapOutputCopier.java#shuffleToDisk

 

 

       ReduceTask用ShuffleRamManager管理写到内存的数据,InMemFSMergeThread通过ShuffleRamManager实时检查从Map获取放到内存的数据,如果内存占用的比率大于阈值,或完成的mem shuffle的个数大于阈值,或等待的shuffle的个数大于阈值,则负责对写入内存的数据进行合并写入到文件中。

ReduceTask.ShuffleRamManager.java#waitForDataToMerge()


符合条件和对内存数据进行归并:

ReduceTask.InMemFSMergeThread.java#doInMemMerge()

 

    LocalFSMerger实时检查从Map获取写到文件的数据,写入的文件个数超过指定阈值时对多个文件进行合并处理。

ReduceTask.LocalFSMerger.java


InMemFSMergeThread和LocalFSMerger线程只有在传输Map数据到Reduce期间运行,传输完毕后停止归并线程,开始reduce处理,reduce处理完后即完成对多个Map数据归并处理,并把最终的数据写入到该job在hdfs上指定的output目录。


0 0
原创粉丝点击