有了上面Mapper输出的内存存储结构和硬盘存储结构讨论,我们来细致分析MapOutputBuffer的流程。首先是成员变量。最先初始化的是作业配置job和统计功能reporter。通过配置,MapOutputBuffer能够获取本地文件系统(localFs和rfs),Reducer的数目和Partitioner。 SpillRecord是文件spill.out{spill号}.index在内存中的相应抽象(内存数据和文件数据就差最后的校验和),该文件保持了一系列的IndexRecord IndexRecord有3个字段,各自是startOffset:记录偏移量。rawLength:初始长度,partLength:实际长度(可能有压缩)。 SpillRecord保持了一系列的IndexRecord,并提供方法用于加入记录(没有删除记录的操作,由于不须要)。获取记录,写文件,读文件(通过构造函数)。 io.sort.record.percent是kvindices和kvoffsets占用的空间比例(缺省是0.05)。 前面的分析我们已经知道kvindices和kvoffsets,假设记录数是N的话,它占用的空间是4N*4bytes,依据这个关系和io.sort.record.percent的值。我们能够计算出kvindices和kvoffsets最多能有多少个记录。并分配相应的空间。參数io.sort.spill.percent指示当输出缓冲区或kvindices和kvoffsets记录数量到达相应的占用率的时候。会启动spill,将内存缓冲区的记录存放到硬盘上。softBufferLimit和softRecordLimit为相应的字节数。 值对<key, value>输出到缓冲区是通过Serializer串行化的。这部分的初始化跟在上面输出缓存后面。接下来是一些计数器和可能的数据压缩处理器的初始化,可能的Combiner和combiner工作的一些配置。 先看生产者。MapOutputBuffer.collect的主要流程是: 这就是说。假设kvstart不等于kvend,系统正在spill,否则。kvstart==kvend。系统处于普通工作状态。 事实上在代码中。我们能够看到非常多kvstart==kvend的推断。 以下我们分情况,讨论kvstart,kvend和kvindex的配合。初始化的时候。它们都被赋值0。 假设spill条件满足,那么,kvindex的值会赋给kvend(这是kvend不等于kvstart),从kvstart和kvend的大小关系,我们能够知道记录位于数组的那一部分(左边是kvstart<kvend的情况,右边是另外的情况)。Spill结束的时候,kvend值会被赋给kvstart,kvend==kvstart又又一次满足。同一时候。我们能够发现kvindex在这个过程中没有变化。新的记录还是写在kvindex指向的位置,然后,kvindex=kvnect,kvindex移到下一个可用位置。 Collect在处理<key。value>输出时。会处理一个MapBufferTooSmallException,这是value的串行化结果太大。不能一次放入缓冲区的指示,这样的情况下我们须要调用spillSingleRecord,特殊处理 |
Hadoop源码分析(MapTask辅助类,II)
转载本文章为转载内容,我们尊重原作者对文章享有的著作权。如有内容错误或侵权问题,欢迎原作者联系我们进行内容更正或删除文章。
上一篇:cygwin
下一篇:Java入门到精通——调错篇之Eclipse No Java virtual machine was found after searching the following locations
提问和评论都可以,用心的回复会被更多人看到
评论
发布评论
相关文章
-
08-Hadoop MapReduce 原理 MR源码调试 MapTask流程mapreduce
-
hadoop 源码分析
job分解为几个task,并返回task头信息 2.MapTask中 计算map task数量 运行map
hadoop 源码 内部类 类图