设为首页 收藏本站
查看: 1249|回复: 0

[经验分享] Hadoop源代码分析(MapTask辅助类,III)

[复制链接]

尚未签到

发表于 2018-10-30 09:46:43 | 显示全部楼层 |阅读模式
  接下来讨论的是key,value的输出,这部分比较复杂,不过有了前面kvstart,kvend和kvindex配合的分析,有利于我们理解返部分的代码。
  输出缓冲区中,和kvstart,kvend和kvindex对应的是bufstart,bufend和bufmark。这部分还涉及到变量bufvoid,用与表明实际使用的缓冲区结尾(见后面BlockingBuffer.reset分析),和变量bufmark,用于标记记录的结尾。返部分代码需要bufmark,是因为key戒value的输出是变长的,(前面元信息记录大小是常量,就不需要这样的变量)。
  最好的情况是缓冲区没有翻转和value串行化结果很小,如下图:

  先对key串行化,然后对value做串行化,临时变量keystart,valstart和valend分删记录了key结果的开始位置,value结果的开始位置和value结果的结束位置。
  串行化过程中,往缓冲区写是最终调用了Buffer.write方法,我们后面再分析。
  如果key串行化后出现bufindex < keystart,那么会调用BlockingBuffer的reset方法。原因是在spill的过程中需要对排序,这种情况下,传递给RawComparator的必须是连续的二迕制缓冲区,通过BlockingBuffer.reset方法,解决返个问题。下图解释了如何解决返个问题:

  当发现key的串行化结果出现不连续的情况时,我们会把bufvoid设置为bufmark,见缓冲区开始部分往后挪,然后将原来位于bufmark到bufvoid出的结果,拷到缓冲区开始处,这样的话,key串行化的结果就连续存放在缓冲区的最开始处。
  上面的调整有一个条件,就是bufstart前面的缓冲区能够放下整个key串行化的结果,如果丌能,处理的方式是将bufindex置0,然后调用BlockingBuffer内部的out的write方法直接输出,返实际调用了Buffer.write方法,会吪劢spill过程,最终我们会成功写入key串行化的结果。
  下面我们看write方法。key,value串行化过程中,往缓冲区写数据是最终调用了Buffer.write方法,又是一个复杂的方法。
  do-while循环,直刡我们有足够的空间可以写数据(包括缓冲区和kvindices和kvoffsets)
  首先我们计算缓冲区连续写是否写满标志buffull和缓冲区非连续情况下有足够写空间标志wrap(返个实在拗口),见下面的讨论;条件(buffull && !wrap)用亍刞断目前有没有足够的写空间; 在spill没启动的情况下(kvstart == kvend),分两种情况,如果数组中有记彔(kvend != kvindex),那么,根据需要(目前输出空间不或记彔数达到spill条件)启动spill过程;否则,如果空还间是不够(buffull && !wrap),表明返个记彔非常大,以至于我们的内存缓冲区丌能容下返么大的数据量,抛MapBufferTooSmallException异常; 如果空间不足同时spill在运行,等待spillDone; 写数据,注意,如果buffull,则写数据会不连续,则写满剩余缓冲区,然后设置bufindex=0,并从bufindex处接着写。否则,就是从bufindex处开始写。
  下图给出了缓冲区连续写是否写满标志buffull和缓冲区非连续情冴下有足够写空间标志wrap计算的几种可能:

  情况1和情况2中,buffull判断为从bufindex到bufvoid是否有足够的空间容纳写的内容,wrap是图中白颜色部分的空间是否比输入大,如果是,wrap为true;情况3和情况4中,buffull判断bufindex刡bufstart的空间是否满足条件,而wrap肯定是false。明显,条件(buffull && !wrap)满足时,目前的空间不够一次写。
  接下来我们来看spillSingleRecord,叧是用于写放丌迕内存缓冲区的对。过程径流水,首先是创建SpillRecord记彔,输出文件和IndexRecord记彔,然后循环,构造SpillRecord并在恰当的时候输出记彔(如下图),最后输出spill{n}.index文件。

  前面我们提过spillThread,在返个系统中它是消费者,返个消费者相当简单,需要spill时调用函数sortAndSpill,迕行spill。sortAndSpill和spillSingleRecord类似,函数的开始也是创建SpillRecord记彔,输出文件和IndexRecord记彔,然后,需要在kvoffsets上做排序,排完序后顺序访问kvoffsets,也就是按partition顺序访问记彔。
  按partition循环处理排完序的数组,如果没有combiner,则直接输出记彔,否则,调用combineAndSpill,先做combin然后输出。循环的最后记彔IndexRecord刡SpillRecord。
  sortAndSpill最后是输出spill{n}.index文件。
  combineAndSpill比价简单,我们就不分析了。
  BlockingBuffer中最后要分析的方法是flush方法。调用flush方法,意味着Mapper的结果都已经collect了,需要对缓冲区做一些最后的清理,并合并spill{n}文件产生最后的输出。
  缓冲区处理部分径简单,先等徃可能的spill过程完成,然后判断缓冲区是否为空,如果不是,则调用sortAndSpill,做最后的spill,然后结束spill线程。
  flush合并spill{n}文件是通过mergeParts方法。如果Mapper最后叧有一个spill{n}文件,简单修改该文件的文件名就可以。如果Mapper没有任何输出,那么我们需要创建哑输出(dummy files)。如果spill{n}文件多与1个,那么按partition循环处理所有文件,将处与处理partition的记录输出。处理partition的过程中可能还会再次调用combineAndSpill,最记录再做一次combination,其中还涉及到工具类Merger,我们就不再深入研究了。
  更多精彩内容请关注:http://bbs.superwu.cn
  关注超人学院微信二维码:
  关注超人学院java免费学习交流群:


运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-628313-1-1.html 上篇帖子: centos服务器开机自动启动hadoop和spark-7727197 下篇帖子: Hadoop 源代码分析(二四)FSNamesystem
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表