问题导读
什么是map本地?
reducer的输入是来自什么地方?
map数据是否被复制随map函数等下发到客户?
次讨论由about云小组发起:主要贡献者为Karmic Koala与立立,由我来整理分享给大家:
你觉得hadoop jar的执行除了分发代码,整个过程是什么样子的。
Karmic Koala:
客户端把jar送给JT,JT将jar放入HDFS,这样所有的TT都有能力访问这个jar。然后,JT 根据 job 指定的 InputFormat 中的定义,将数据切成 input split。每一个split对应一个map。
对应一个map task,每个task会根据其输入数据的所在DN距离候选TT的距离选择最近的TT去执行该task,称为 attempt。尝试成功,就执行下一个map task;如果失败,JT会调度给另一个TT。(这里需要注意的是为什么选距离最近的,因为这样获取数据最方便,并且真正的被处理的数据并没有下发给map,而是在执行任务的时候,根据传递的信息去寻找数据。如同寻找一个人一样,我只要知道你的地址,我就能找到你的家了)
立立:
split在client端就划分好了(新版这样,旧版本是在JT端划分split)
Karmic Koala:
map 输出会存入本地的partition,决定partition的,默认是key,通过 hash(key) % numOfReducer 决定 partition。这个数据位于map本地,不在HDFS。
然后是 reducer 开始接任务,reducer 会联系每一个 map,请求自己对应的 partition 数据,数据请求下来之后,进行 merge sort,至此就做好了 reducer 的输入了。(这里说明了reducer的输入是来自什么地方)
立立:
map本地和HDFS如何理解,mapreduce作业都运行在datanode上,datanode上的存储空间不都属于HDFS么
reducer 的输出存入 HDFS 没啥可说的,每个 reducer 对应一个文件。
好像我记得map的输出是先到内存一个缓冲区,缓冲区满后才spill到磁盘吧
Karmic Koala:
MR运行于TT上,HDFS 的block存储于 DN 的 dfs.data.dir 目录下;而 map 输出的中间结果则保存于 mapred.local.dir 目录下(map本地目录)。
一般来说二者都会指向同一个物理硬盘,因此需要保留20-30%的空间给 mapreduce。所以需要额外设置 dfs.datanode.du.reserved ,这个值告诉 HDFS DN,物理硬盘保留多少空间不用。这个空间一般是20-30%整个硬盘空间。
立立:
每个map task都有一个循环利用的缓冲区(默认大小是100M,通过io.sort.mb设置),它有输出先放到缓冲区里。当缓冲区满80%(该值可以通过io.sort.spill.percent设置)后,后台线程会把它spill到磁盘。当缓冲区填满100%时,map的输出没地方做,map task将被阻塞。
在被写入磁盘之前,数据首先会被分区(根据hadoop的Partitioner),在每个分区中数据会被放到内存中进行排序。MapTask结束的时候所有的分区会被合并成一个排序好的文件。 这里说的磁盘是你所说的mapred.local.dir 目录么?
Karmic Koala:
reduce 从各个 map 上取得的数据也会存入 mapred.local.dir 目录。
是的。这个分区、合并、局部排序好的数据会保存于 mapred.local.dir 目录。
立立:
磁盘和HDFS的概念差不多理解了,应该是HDFS是部分磁盘空间,以为磁盘还要作其他用处,比如跑Linux系统,存储一些系统所需文件。
Karmic Koala:
Hadoop 一般部署上会要求专盘专用。系统盘上不用于数据存储。如果要是使用系统盘的话,reserved 还需要考虑系统必须的可用空间。另外,默认情况下,磁盘格式化的时候会给root留有5%的可用空间。对于专用的数据盘,这部分空间应该在格式化时候释放出来。不然磁盘依旧无法充分利用
存储于 dfs.data.dir 的东西实际上是通过 NN 保存的 HDFS 文件,因此,这部分数据一般在别的DN上都有备份。而存储于 mapred.local.dir 的是纯粹的本地文件,不位于HDFS,别的DN上也不会有。而且是临时的,MR job 结束后,会自动删除掉。
----------------------------------------------------------------------------------------------------------------------------
上面讲了不少的内容,这里总结一下:hadoop jar 执行原理,因为是分布式,在执行的过程中,会涉及到分发,那么具体怎么分发的那?下面引用一些信息:来自深度了解mapreduce---MapReduce源码分析总结
job.jar, job.split和job.xml。
job.xml: 作业配置,例如Mapper, Combiner, Reducer的类型,输入输出格式的类型等。
job.jar: jar包,里面包含了执行此任务需要的各种类,比如 Mapper,Reducer等实现。
job.split: 文件分块的相关信息,比如有数据分多少个块,块的大小(默认64m)等。
这三个文件在hdfs上的路径由hadoop-default.xml文件中的mapreduce系统路径mapred.system.dir属性 + jobid决定。mapred.system.dir属性默认是/tmp/hadoop-user_name/mapred/system。写完这三个文 件之后, 此方法会通过RPC调用master节点上的JobTracker.submitJob(job)方法,此时作业已经提交完成。
1 JobTracker初始化Job1.1 JobTracker.submitJob() 收到请求
当JobTracker接收到新的job请求(即submitJob()函数被调用)后,会创建一个JobInProgress对象并通过它来管理和调度任务。JobInProgress在创建的时候会初始化一系列与任务有关的参数,调用到FileSystem,把在JobClient端上传的所有任务文件下载到本地的文件系统中的临时目录里。这其中包括上传的*.jar文件包、记录配置信息的xml、记录分割信息的文件。
在这个过程中,还会记录该RawSplit块对应的所有在HDFS里的blocks所在的DataNode节点的host,这个会在RawSplit创建时通过FileSplit的getLocations()函数获取,该函数会调用DistributedFileSystem的getFileCacheHints()获得 从上面我们可以得出,hadoop jar执行的过程中,会传递三个文件,这里具体不就在写了。当map执行的时候则会根据传递的记录分割信息的文件去寻找数据。
|
|