在本节中,我们主要来学习MapTask的内部实现。 
         
         整体执行流程 
 
         如上图示,MapTask的整个处理流程分五个阶段: 
         ●read阶段:通过RecordReader从InputSplit分片中将数据解析成一个个key/value。 
         ●map阶段:将由RecordReader解析出的key/value交给map()方法处理,并生成一个个新的key/value。 
         ●collect阶段:将map()中新生成key/value由OutpCollector.collect()写入内存中的环形数据缓冲区。 
         ●spill阶段:当环形缓冲区达到一定阀值后,会将数据写到本地磁盘上,生成一个spill文件。在写文件之前,会先将数据进行一次本地排序,必要的时候(按配置要求)还会对数据进行压缩。 
         ●combine阶段:当所有数据处理完后,将所有的临时的spill文件进行一次合并,最终之生成一个数据文件。
     
         接下来我们会对该流程中最重要的collect、spill和combine三个阶段进行更深入的学习。 
         Collect过程 
         前阶段的map中新生成key/value对后,会调用OutpCollector.collect(key,value),在该方法内部,先调用Partitioner.getPartition()获取该记录的分区号,然后将<key,value,partition>传给MapOutputBuffer.collect()作进一步的处理。 
         MapOutputBuffer内部使用了一个内部的环形的缓冲区来暂时保存用户的输出数据,当缓冲区使用率达到一定阀值后,由SpillThread线程将缓冲区中的数据spill到本地磁盘上,当所有的数据处理完毕后,对所有的文件进行合并,最终只生成一个文件。该数据缓冲区直接用想到MapTask的写效率。 
         环形缓冲区使得collect阶段和spill阶段可以并行处理。 
         MapOutputBuffer内部采用了两级索引结构,涉及三个环形的内存缓冲区,分别是kvoffsets、kvindices和kvbuffer,这个环形缓冲区的大小可以通过io.sot.mb来设置,默认大小是100MB,图示如下: 

         kvoffsets即偏移量索引数组,用于保存key/value在kvindices中的偏移量。一个key/value对在kvoffsets数组中占一个int的大小,而在kvindices数组中站3个int的大小(如上图示,包括分区号partition,key的起始位置和value的起始位置)。 
         当kvoffsets的使用率超过io.sort.spill.percent(默认为80%)后,便会触发SpillTread线程将数据spill到磁盘上。 
         kvindices即文职索引数组,用于保存实际的key/value在数据缓冲区kvbuffer中的起始位置。 
         kvbuffer即数据局缓冲区,用于实际保存key/value,默认情况下可使用io.sort.mb的95%,当该缓冲区使用率使用率超过io.sort.spill.percent后,便会触发SpillTread线程将数据spill到磁盘上。

Spill过程 
         在collect阶段的执行过程中,当内存中的环形数据缓冲区中的数据达到一定发之后,便会触发一次Spill操作,将部分数据spill到本地磁盘上。SpillThread线程实际上是kvbuffer缓冲区的消费者,主要代码如下:

  1. spillLock.lock();
  2. while(true){
  3. spillDone.sinnal();
  4. while(kvstart == kvend){
  5. spillReady.await();
  6. }
  7. spillDone.unlock();
  8. //排序并将缓冲区kvbuffer中的数据spill到本地磁盘上
  9. sortAndSpill();
  10. spillLock.lock;
  11. //重置各个指针,为下一下spill做准备
  12. if(bufend < bufindex && bufindex < bufstart){
  13. bufvoid = kvbuffer.length;
  14. }
  15. vstart = vend;
  16. bufstart = bufend;
  17. }
  18. spillLock.unlock();

sortAndSpill()方法中的内部流程是这样的: 
         第一步,使用用快速排序算法对kvbuffer[bufstart,bufend)中的数据排序,先对partition分区号排序,然后再按照key排序,经过这两轮排序后,数据就会以分区为单位聚集在一起,且同一分区内的数据按key有序; 
         第二步,按分区大小由小到大依次将每个分区中的数据写入任务的工作目录下的临时文件中,如果用户设置了Combiner,则写入文件之前,会对每个分区中的数据做一次聚集操作,比如<key1,val1>和<key1,val2>合并成<key1,<val1,val2>>; (不确定是否正确这句话,有的说是在merge时将相同key的value合成list,待我研究下,)
         第三步,将分区数据的元信息写到内存索引数据结构SpillRecord中。分区的元数据信息包括临时文件中的偏移量、压缩前数据的大小和压缩后数据的大小。

Combine过程 
         当任务的所有数据都处理完后,MapTask会将该任务所有的临时文件年合并成一个大文件,同时生成相应的索引文件。在合并过程中,是以分区文单位进行合并的。 
         让每个Task最终生成一个文件,可以避免同时打开大量文件和对小文件产生随机读带来的开销。

Hadoop深入学习:MapTask详解的更多相关文章

  1. iPhone应用开发 UITableView学习点滴详解

    iPhone应用开发 UITableView学习点滴详解是本文要介绍的内容,内容不多,主要是以代码实现UITableView的学习点滴,我们来看内容. -.建立 UITableView DataTab ...

  2. Hadoop Hive sql语法详解

    Hadoop Hive sql语法详解 Hive 是基于Hadoop 构建的一套数据仓库分析系统,它提供了丰富的SQL查询方式来分析存储在Hadoop 分布式文件系统中的数据,可以将结构 化的数据文件 ...

  3. Hadoop生态圈-Kafka配置文件详解

    Hadoop生态圈-Kafka配置文件详解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.默认kafka配置文件内容([yinzhengjie@s101 ~]$ more /s ...

  4. hadoop应用开发技术详解

    <大 数据技术丛书:Hadoop应用开发技术详解>共12章.第1-2章详细地介绍了Hadoop的生态系统.关键技术以及安装和配置:第3章是 MapReduce的使用入门,让读者了解整个开发 ...

  5. Hadoop基础-Idea打包详解之手动添加依赖(SequenceFile的压缩编解码器案例)

    Hadoop基础-Idea打包详解之手动添加依赖(SequenceFile的压缩编解码器案例) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.编辑配置文件(pml.xml)(我 ...

  6. 《Hadoop应用开发技术详解》

    <Hadoop应用开发技术详解> 基本信息 作者: 刘刚 丛书名: 大数据技术丛书 出版社:机械工业出版社 ISBN:9787111452447 上架时间:2014-1-10 出版日期:2 ...

  7. Eclipse IDE for C/C++ Developers和MinGW安装配置C/C++开发学习环境详解

    Eclipse IDE for C/C++ Developers和MinGW安装配置C/C++开发学习环境详解 操作系统:Windows 7 JDK版本:1.6.0_33 Eclipse版本:Juno ...

  8. Hadoop MapReduce执行过程详解(带hadoop例子)

    https://my.oschina.net/itblog/blog/275294 摘要: 本文通过一个例子,详细介绍Hadoop 的 MapReduce过程. 分析MapReduce执行过程 Map ...

  9. 【大数据】Linux下安装Hadoop(2.7.1)详解及WordCount运行

    一.引言 在完成了Storm的环境配置之后,想着鼓捣一下Hadoop的安装,网上面的教程好多,但是没有一个特别切合的,所以在安装的过程中还是遇到了很多的麻烦,并且最后不断的查阅资料,终于解决了问题,感 ...

随机推荐

  1. EM64T和64位是不是一个概念啊?他们有什么区别啊,怎么区分啊?

    首先我们要解决什么是64位这个问题.究竟什么是64位处理器呢?64 bit是相对于32 Bit而言的,这个位数指的是CPU GPRs(General-Purpose Registers,通用寄存器)数 ...

  2. java调用python

    本文记录下使用jython包来实现java代码中调用Python. 一.Maven加入 <dependency> <groupId>org.python</groupId ...

  3. 【phonegap】IOS按HOME键,程序进入suspended状态,再调出,界面出现文字丢失问题

    发现丢失的都是时间类型的,把日期型改成 yyyy年mm月dd日 时间从冒号表示(12:00)改成中文表示,12点00分,就不再丢失了. 未找到真正原因

  4. BurpSuite—-Sequencer模块(定序器)

    一.简介 Burp Sequencer是一种用于分析数据项的一个样本中的随机性质量的工具.你可以用它来测试应用程序的session tokens(会话tokens)或其他重要数据项的本意是不可预测的, ...

  5. vue中使用markdown富文本,并在html页面中展示

    想给自己的后台增加一个markdown编辑器,下面记录下引用的步骤 引入组件mavon-editor 官网地址:https://github.com/hinesboy/mavonEditor // 插 ...

  6. eclipse+minGW 调试ffmpeg错误:No symbol table is loaded. Use the "file" command.

    转载地址:http://www.blogjava.net/fancydeepin/archive/2012/11/19/391520.html 数据结构第二篇:  eclipse SDK 安装和配置 ...

  7. Django中间件限制用户访问频率

    原:https://blog.csdn.net/weixin_38748717/article/details/79095399 一.定义限制访问频率的中间件 common/middleware.py ...

  8. PyInstaller打包成exe可执行文件

    PyInstaller 安装pyinstaller 对于那些网络比较稳定,能够流畅使用pip源地址的用户,直接下面的命令就可以搞定: pip install pyinstaller 通常我们会下载源码 ...

  9. iis7+的虚拟目录:未能加载程序集“**”。请确保在访问该页之前已经编译了此程序集

    在使用win8系统后,突然想运行iis,于是在windows组件中启用iis,并aspnet_regiis.exe -i注册iis后,于是开始发布了一个站点,一切正常 继而,在该站点下添加虚拟目录,然 ...

  10. java5 Condition用法--实现线程间的通信

    Condition的功能类似在传统线程技术中的Object.wait()和Object.natify()的功能,传统线程技术实现的互斥只能一个线程单独干,不能说这个线程干完了通知另一个线程来干,Con ...