群里面有tx问到Hadoop的Map Task是怎么工作的,局部性是怎么保证的,想起来当初自己刚刚接触的时候,也是非常好奇这个问题,甚至还做过一些实验来验证,事实上Hadoop的Map Task的局部性在单Job执行的情况下还是效果非常好的。UC Berkeley的RAD实验室有一个GG在这个方向做的非常好,建议大家可以去他主页上看看,叫Matei Zaharia.
整个Hadoop从JobClient进行job提交到TaskTracker得到Task开始执行,大概是经过了下面几个过程(因为Hadoop中有Task和Job的区别,翻译成任务怕引起歧义,故本文都是用英文单词来表示这两个意思)
1,JobClient.runJob()开始运行Job
这个是用户接口。其直接调用JobClient.submitJob()方法
2,JobClient.submitJob()向JobTracker节点提交任务,进行数据划分
submitJob方法中调用InputFormat接口的getSplites方法获得一个InputSplit[]数组,并且将该Split按照大小排序,最大的放在前面(分割split的标准时MapTask的数目)。分割之后,将InputSplit[]数组信息materialize到JobTracker的本地文件系统中。之后真正的开始提交任务:jobSubmitClient.submitJob(jobID). jobSubmitClient可以处理JobClient在JobTracker上运行的情况,也可以处理JobTracker在远端的情况。
3,JobTracker创建JobInProgress对象
JobTracker将在本地创建JobInProgress对象和TaskInProgress对象。JobInProgress对象在创建的时候会初始化较多内容,包括:文件系统中job对应的jar文件,并将其从HDFS拷贝到本地文件系统的SYSDIR下,新建nonLocalMaps, nonLocalRunningMaps, runningMapCache等Map。之后经过一系列比较复杂的Job调度策略,被选中的Job的JobInProgress的initTasks()函数执行,此处进行局部化相关的操作。
initTasks()是单独的线程,所以其不会阻塞JobTracker的执行。initTasks完成以下工作:
a,读入input splits:前面说到了,InputSplit文件会被写入到JobTracker的本地文件系统中,而此时我们要作的就是读入该文件,读出为RawSplit类型的数组。
b,为每一个RawSplit创建一个TaskInProgress实例,用来代表一个MapTask。
c,根据splits得到一个Map实例:nonRunningMapCache。该Map实例声明如下:Map<Node, List<TaskInProgress>> nonRunningMapCache。
d,生成reduce任务,以及setup任务,cleanup任务等等。
4,TaskTracker通过心跳协议请求任务
每隔HEARTBEAT_INTERVAL的时间,TaskTracker和JobTracker进行一次通讯。如果本地空闲,则会请求任务执行。
5,JobTracker通过obtainNewMapTask返回给TaskTracker一个合适的任务
心跳协议的另一端JobTracker通过obtainNewMapTask来返回给TaskTracker一个合适的Map任务。任务通过findNewMapTask来查找合适的Map任务。findNewMapTask中说的比较详细,过程如下:
调度一个map任务时,有两个cache和一个list。
一个cache用来存储未运行的任务——nonRunningMapCache
一个cache用来存储正在运行的任务——RunningMapCache
list用来存储用用空的locations的tip,如果所有的tip都有location信息时,此list为空。
首先我们查找未运行cache,如果miss了再查找在运行中的cache,查找的顺序如下:
1,从本地节点到root节点,从下往上查找
2,宽度优先策略
如果都失败,则线性搜索list
事实上所有non-running的map任务的TaskInProgress都放置在Map实例nonRunningMapCache中,该Map的Key为Node,Value就是该Node上可以本地执行的map任务。该信息是由createCache函数在阶段3中生成的。
findNewMapTask比较复杂,可以仔细看一下。
6,TaskTracker获取TaskTrackerAction数组
略
7,TaskTracker调用startNewTask启动新任务
略
大致过程就是这样,本人也属新手,如有纰漏,还请指正。