【无标题】Hadoop

MapReduce
执行流程
MapTask执行流程

  1. Read:读取阶段
    1. MapTask会调用InputFormat中的 getSplits 方法来对文件进行切片
    2. 切片之后,针对每一个Split,产生一个 RecordReader 流用于读取数据
    3. 数据是以 Key-Value 形式来产生,交给 map 方法来处理。每一个键值对触发调用一次 map 方法
  2. Map:映射阶段
    1. map 方法在获取到键值对之后,按照要求对键值对中的数据进行拆分解析,解析之后按照要求输出键值对形式的结果
  3. Collect:收集阶段
    1. MapTask拆分产生数据之后,并不是直接将数据传输给ReduceTask,而是会调用
      OutputCollector.collect 方法来收集输出结果
    2. OutputCollector.collect 在收集到数据之后,会先按照指定的规则,对数据进行分区,
      分区完成之后,会将数据写到缓冲区中
    3. 缓冲区本质上是一个环形的字节数组,默认大小是100M(可以通过属性
      mapreduce.task.io.sort.mb 来调节),默认阈值是0.8(可以通过属mapreduce.map.sort.spill.percent 来调节)
  4. Spill:溢写阶段
    1. 当缓冲区使用达到指定阈值的时候,MapTask会将缓冲区中的数据冲刷(flush)到磁盘上,这
      个过程称之为溢写(spill)
    2. 在溢写的时候,会按照如下步骤进行
      1. 排序(sort)。此时,是将毫无规律的数据整理成有序数据,采用的Quick Sort(快速排
        序)。需要注意的是,数据在排序的时候,是按照分区内进行的排序,即先按照分区大小进行分区号的升序,然后每一个分区内按照指定规则排序。因此,数据是分区内有序
      2. 合并(combine)。如果用户指定了 Combiner ,那么此时会将数据进行合并处理
      3. 写出(flush)。按照分区的顺序,将每一个分区中的数据依次写入任务的工作目录的临时
        文件 output/spillN.out 中。 N 表示溢写次数。溢写次数不能完全由原始数据大小来决定,还得考虑 map 方法的处理过程。此时,单个结果文件中是分区且有序的,整体而
        言是局部有序
      4. 压缩(compress)。如果用户指定了对MapTask的结果进行压缩,那么数据在写出之后还
        会进行压缩处理
      5. 记录(record)。将分区数据的元信息记录到内存索引数据结果 SpillRecord 中。元信息
        中包含:每一个分区在每一个临时结果文件中的偏移量(offset),每一个分区压缩前的数据大小以及压缩后的数据大小。如果 SpillRecord 中记录的所有的元信息大小之和不超过1M,那么 SpillRecord 中的数据也会写到 output/spillN.out.index 中
  5. Merge:合并阶段
    1. 当MapTask将所有的数据处理完成之后,会将所有的临时结果文件 spillN.out 合并(merge)
      成一个大的结果文件 output/file.out ,同时会为这个文件生成索引文件 file.out.index
    2. 在merge过程中,数据会再次进行分区。分区之后数据会再次进行排序。注意,此次排序是
      将局部有序的数据整理成整体有序,采用的是Merge Sort(归并排序)
    3. 在merge过程中,如果指定了Combiner,那么数据会进行combine操作
    4. merge的时候,默认情况下,是每10个(可以通过属性 mapreduce.task.io.sort.factor 来调节)小文件合并成1个大文件,通过多次合并,最后会产生一个结果文件 file.out 。这样子,能够有效的避免同时打开大量文件带来的开销
    5. 注意:无论是否会进行Spill过程,最后都会产生一个 file.out 文件!!!
      ReduceTask执行流程
  6. 当达到启动阈值的时候,ReduceTask就会启动。默认情况下,启动阈值是0.05,即5%的MapTask结束ReduceTask就会启动。可以通过属性mapreduce.job.reduce.slowstart.completedmaps来调节
  7. ReduceTask启动之后,会启动fetch线程来抓取数据。默认情况下,每一个ReduceTask最多可以启动5个fetch线程来抓取数据。可以通过属性 mapreduce.reduce.shuffle.parrellelcopies来调节
  8. fetch启动之后,会通过http请求的get请求来获取数据,在请求的时候,会携带参数表示当前的分
    区号。MapTask在收到请求之后,根据参数(分区号)来解析 file.out.index 文件,从中获取指定分区的位置,然后才会读取 file.out ,将对应分区的数据返回
  9. fetch线程在抓取到数据之后,会先对数据进行大小判断。如果数据超过了ReduceTask的缓冲区阈值,那么会将数据直接以文件形式写到磁盘上;如果没有超过ReduceTask的缓冲区阈值,那么就
    先放到缓冲区中
    1. 缓冲区的大小由属性 mapreduce.reduce.shuffle.input.buffer.percent 来决定,默认
    是0.7,是ReduceTask执行过程中允许占用内存的70%
    2. 缓冲区的阈值由属性 mapreduce.reduce.shuffle.merge.percent 来决定,默认是0.66,
    即缓冲区大小的66%
  10. fetch线程在抓取数据的同时,ReduceTask会启动两个后台线程将抓取来的数据进行merge,以防内存以及磁盘占用过多
  11. 所有的fetch线程完成之后,ReduceTask会将抓取来的所有的数据进行排序。同样,此时也是将局部有序的数据整理成整体有序的数据,所以依然采用的是归并排序(Merge Sort)
  12. 经过排序和merge,最终产生了一个大的临时文件来交给ReduceTask来处理。此时ReduceTask
    会将相同的键对应的值放到一起,形成一个伪迭代器(本质上就是一个流,来读取刚刚产生的临时
    文件),这个过程称之为分组(group)。也正因为是伪迭代器(将流包装成了迭代器,临时文件读取完
    之后就会被销毁),所以只能遍历一次!
  13. 分组完成之后,每一个键调用一次 reduce 方法,按照指定的规则来对数据进行聚合
  14. reduce 处理完之后,会将结果传递给 OutputFormat ,按照指定规则将数据以指定形式写出到指
    定位置
    流程图
    在这里插入图片描述
    常见优化方案
  15. 减少MapTask的溢写次数。溢写是将数据写到磁盘上,程序和磁盘交互次数越多,效率越低;此
    时,如果需要提高效率,就可以考虑减少MapTask和磁盘的交互次数
    1. 调节缓冲区的大小。通过 mapreduce.task.io.sort.mb 来调节,实际过程中,一般会将这
    个值调节为250M~400M
    2. 调节缓冲区阈值的大小。通过属性 mapreduce.map.sort.spill.percent 来调节
  16. 减少Merge次数。通过属性 mapreduce.task.io.sort.factor 来调节
  17. 增加Combiner。如果计算可以传递,那么建议在程序中使用Combiner。根据经验,使用
    Combiner,大约可以提升40%的效率
  18. 减少Reduce。如果MapTask处理完成之后,不需要使用Reduce聚合,那么此时可以直接省略
    Reduce
  19. 合理设置ReduceTask的执行内存。默认情况下,每一个ReduceTask最多占用1G内存,如果试图
    超过1G内存,就会被kill掉
    1. 调大ReducedTask的执行内存。通过 mapreduce.reduce.memory.mb 属性来调节,单位是
      MB,默认值是1024
    2. 调大缓冲区的占比。通过 mapreduce.reduce.shuffle.input.buffer.percent 属性来调
    3. 调大缓冲区的阈值。通过 mapreduce.reduce.shuffle.merge.percent 属性来调节
  20. 增加fetch线程的数量。通过 mapreduce.reduce.shuffle.parrellelcopies 属性来调节
  21. 可以考虑对数据进行压缩。即将MapTask产生的结果进行压缩之后传递给ReduceTask,但是这种方案是在网络和解压效率之间进行了平衡/对比
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值