Hadoop1中Reduce task内部实现原理

来源:互联网 发布:列式数据库 olap 编辑:程序博客网 时间:2024/06/13 03:22

与map task 一样,reduce task也分为4种,即job-setup task、job-cleanup task、task-cleanup task和reduce task。本文中重点介绍reduce task。reduce task要从各个map task上读取一片数据,经排序后,以组为单位交给用户编写的reduce( )函数处理,并将结果写到HDFS上

reduce task整体流程
reduce task的整体计算流程,共分为5个阶段
1、shuffle阶段:也称为copy阶段。reduce task从各个map task上远程拷贝一片数据,并针对某一片数据,如果其大小超过一定值,则写到磁盘上,否则直接放到内存中。
2、merge阶段:在远程拷贝数据的同时,reduce task启动了两个后台线程对内存和磁盘上的文件进行合并,以防止内部使用过多或磁盘上文件过多
3、sort阶段:按照mapreduce语义,用户编写的reduce()函数输入数据是按key进行聚集的一组数据,为了将key相同的数据聚在一起,hadoop采用了基于排序的策略。由于各个map task 已经实现对key相同的数据聚在一起,hadoop采用了基于排序的策略。由于各个map task 已经实现对自己的处理结果进行了局部排序,因此reduce task只需对所有数据进行一次归并排序即可。
4、reduce阶段:在该阶段中,reduce task将每组数据依次交给用户编写的reduce()函数处理
5、write阶段:reduce()函数将计算结果写到hdfs上。
这里写图片描述

shuffle和merge阶段分析
在reduce task中,shuffle阶段和merge阶段是并行进行的,当远程拷贝数据量达到一定值后,便会触发相应的合并线程对数据进行合并,这2个阶段均是由类reducecopier实现的,这个类实现比较复杂,shuffle&merge阶段可进一步划分为三个子阶段
1、准备运行完成的map task列表
GetMapEventsThread线程周期性通过RPC从task tracker获取已完成map task列表,并保存到映射表mapLocations(保存了task tracker host与已完成任务进行的映射关系)中。为了防止出现网络热点,reduce task通过对所有task tracker host进行混洗操作以打乱数据拷贝顺序,并将调整后的map task输出数据位置保存到schedulerCopies列表中
2、远程拷贝数据
reduce task同时启动多个mapOutputCopier线程,这些线程从schedulerCopies列表中获取map task输出位置,并通过HTTP Get远程拷贝数据,对于获取的数据分片,如果大小超过一定值,则存放到磁盘上,否则直接放到内存中
3、合并内存文件和磁盘文件
为了防止内存或者磁盘上的文件数据过多,reduce task启动了localFSMerger和InMeMFSMergeThread两个线程分别对磁盘和内存上的文件进行合并
这里写图片描述

详细解析每个阶段的内部实现细节
1、之前说到过tasktracker启动了MapEventsFetcherThread线程,该线程会周期性通过RPC从jobtracker上获取已经运行完成了的map task列表,并保存到TaskCompletionEvent类型的列表allMapEvents中。
而对于reduce task而言,它会启动GetMapEventsThread线程,该线程周期性通过RPC从Tasktracker上获取已运行完成的Map Task列表,并将成功运行完成的Map task放到列表mapLocations中,

这里写图片描述

为了避免出现数据访问热点,reduce task不会直接将列表mapLocations中的map task输出数据位置交给MapOutputCopier线程,而是事先进行一次预处理:将所有tasktracker host进行混洗操作,然后保存到schedulerCopies列表中,而MapOutputCopier线程将从该列表中获取待拷贝的map task输出数据位置,需要注意的是,对于一个tasktracker而言,曾拷贝失败的map task将优先获得拷贝机会
2、远程拷贝数据
reduce task同时启动mapred.reduce.parallel.copies个数据拷贝线程MapOutputCopier,该线程从schedulerCopies列表中获取map task数据输出描述对象,并利用HTTP Get从对应的tasktracker远程拷贝数据,如果数据分片大小超过一定值,则将数据临时写到工作目录下,否则直接保存到内存中,不管是保存到内存中还是磁盘上,MapOutputCopier均会保存一个MapOutputCopier对象描述数据的元信息,如果数据被保存到内存中,则将该对象添加到列表mapOutputsFilesInMemory中,否则将该对象保存到列表麻婆OutputFilesOnDisk中。
在reduce task中,大部分内存用于缓存从map task端拷贝的数据分片,这些内存占用JVM max heap size的mapred.job.shuffle.input.buffer.percent倍,并由类shuffleRamManager管理,reduce task规定,如果一个数据分片大小未超过该内存的0.25倍,则可存放到内存中,如果MapOutputCopier线程要拷贝的数据分片可存放到内存中,则它先要向shuffleRamManager申请相应的内存,待同意后才会正式拷贝数据,否则需要等待它释放内存。
由于远程拷贝数据可能需要跨网络读取多个节点上的数据,期间很容易由于网络或者磁盘等原因造成读取失败,因此提供良好的容错机制是非常有必要的,当出现拷贝错误时,reduce task提供了以下几个容错机制。

1、如果拷贝数据出错次数超过abortFailureLimit,则杀死该reduce task,其中,abortFailureLimit计算方法如下
abortFailureLimit=max{30,numMaps/10}
2、如果拷贝数据出错次数超过maxFetchFailuresBeforeReporting,则进行一些必要的检查,以决定是否杀死该reduce task3、如果前2个条件均不满足,则采用对数回归模型推迟一段时间后重新拷贝对应Map task的输出数据,其中延迟时间delayTime的计算方法如下
delayTime=10000*1.3^noFailedFetches其中noFailedFetces为拷贝错误次数

3、合并内存文件和磁盘文件
前面提到,reduce task从map task端拷贝的数据,可能保存到内存或者磁盘上,随着拷贝数据的增多,内存或者磁盘上的文件数目也必将增多,为了减少文件数目,在数据拷贝过程中,线程LocalFSMerger和InMemFsMergeThread将分别对磁盘和内存上的文件进行合并
对于磁盘上文件,当文件数目超过(2*ioSortFactor-1)后,线程LocalFSMerger会从列表mapOutputFilesOnDisk中取出最小的ioSortFactor个文件进行合并,并将合并后的文件再次写到磁盘上
对于内存中的文件,当满足以下几个条件之一时,InMemFSmergeThread线程会将内存中所有数据合并后写到磁盘上
1、所有数据拷贝完毕后,关闭shuffleRamManager
2、shuffleRamManager中已使用内存超过可用内存mapred.job.shulffle.merge.percent倍且内存文件数目超过2个
3、内存中的文件数目超过mapred.inmem.merge.threshold
4、阻塞在shuffleRamManager上的请求数目超过拷贝线程数目mapred.reduce.parallel.copies的75%

sort和reduce阶段分析
当所有数据拷贝完成后,数据可能存放在内存中或者磁盘上,此时还不能将数据直接交给用户编写的reduce()函数处理,根据mapreduce语义,reduce task需将key值相同的数据聚集到一起,并按组将数据交给reduce()函数处理,为此,hadoop采用了基于排序的数据聚集策略。前面提到,各个map task已经事先对自己的输出分片进行了局部排序,因此,reduce task只需进行一次归并排序即可保证数据整体有序,为了提高效率,hadoop将sort阶段和reduce阶段并行化。在sort阶段,reduce task为内存和磁盘中的文件建立了小顶堆,保存了指向该小顶堆根节点的迭代器,且该迭代器保证了以下两个约束条件
1、磁盘上文件数目小于io.sort.factor
2、当reduce阶段开始时,内存中数据量小于最大可用内存的mapred.job.reduce.input.buffer.percent
在reduce阶段,reduce task不断地移动迭代器,以将key相同的数据顺次交给reduce()函数处理,期间移动迭代器的过程实际上就是不断调整小顶堆的过程,这样,sort和reduce可并行进行

0 0
原创粉丝点击