在前面介绍Hadoop的Reduce任务执行框架的时候说过,作业的每一个Map任务被执行完之后,它们的输出结果均保存在各自执行节点的本地磁盘上,当reduce任务执行的时候,它需要自己去到所有的Map节点上取回属于自己的map输出,直到属于自己的所有map输出copy到本地,reduce任务才开始接下来的工作。那么,Reduce是如何从Map节点取回自己的输入数据呢?这就是本文即将要详细讲述的内容——Map输出复制器ReduceCopier。
相关阅读:?Where=Nkey&Keyword=Hadoop
Map输出复制器ReduceCopier主要有四大组件:复制线程(MapOutputCopier)、合并线程(本地文件合并线程LocalFSMerger、内存合并线程InMemFSMergeThread)、Map任务事件获取线程、任务管理器。复制线程就是通过http协议从成功执行了某一map任务的TaskTracker上获取该map任务的输出结果(属于自己的);合并线程就是将所有的属于自己的map输出合并成一个输出结合作为自己的reduce操作输入;Map任务事件获取线程不断地从负责执行该Reduce任务的TaskTracker上获取已经完成或者已经放弃的map任务,然后将这些map任务添加/更新到复制任务管理器;任务管理器负责管理已经完成的map输出复制任务、正在执行的map输出复制任务、待调度的map输出复制任务、放弃的map输出复制任务等。下面先来整体的看看这些工作组件是如何来统一工作的吧!
从上面的结构框架图中,我们可以发现Map输出复制器ReduceCopier中所有线程(复制线程、合并线程)的任务均来自Map任务事件获取线程,所以在接下来的讨论中,我将首先从Map任务事件获取线程讲起。
1.Map任务事件获取线程
MapEventGetThread线程每隔一段时间(目前hadoop-0.2.0版本是1000ms)就会就会从它的TaskTracker上获取一批当前作业的map任务事件,利用这些map任务事件来更新任务管理器,具体的过程如下:
2.任务管理器
这里的任务管理器(TaskManager)在ReduceMap中没有任何描述,只是我从中抽象出来的一个概念,它一方面管理各种任务队列及相关集合,另一方也负责调度任务。它所管理的任务队列包括:
Set<TaskID> copiedMapOutputs //保存已经成功完成复制map输出的对应Map任务
List<MapOutputLocation> retryFetches //保存复制失败有可再试的Map实例任务
Map<String,List<MapOutputLocation>> mapLocaltions //按照复制任务所在的主机划分任务
List<MapOutputLocation> scheduledCopies //将要被执行的任务
Set<String> uniqueHosts //正在执行复制任务的主机
Map<String,Long> penaltyBox //正在受惩的主机
Set<TaskAttemptID> obsoleteMapIds //不需要执行复制的Map实例任务
Set<TaskID> fetchFailedMaps //复制失败的Map任务
Map<TaskAttemptID,Integer> mapTaskToFailedFetchesMap //复制Map实例任务输出失败的次数
那么,他有事如何调度的呢?其实,这个过程还是比较的复杂的。