MapReduce的shuffle原理

1.shuffle简图

2.shuffle细节图

分区用到了分区器,默认分区器是HashPartitioner

源码:

public class HashPartitioner<K2, V2> implements Partitioner<K2, V2> {

  public void configure(JobConf job) {}

  /** Use {@link Object#hashCode()} to partition. */
  public int getPartition(K2 key, V2 value,
                          int numReduceTasks) {
    return (key.hashCode() & Integer.MAX_VALUE) % numReduceTasks;
  }

}

3.map端

  • 每个map任务都有一个对应的环形内存缓冲区;输出是kv对,先写入到环形缓冲区(默认大小100M),当内容占据80%缓冲区空间后,由一个后台线程将缓冲区中的数据溢出写到一个磁盘文件

  • 在溢出写的过程中,map任务可以继续向环形缓冲区写入数据;但是若写入速度大于溢出写的速度,最终造成100m占满后,map任务会暂停向环形缓冲区中写数据的过程;只执行溢出写的过程;直到环形缓冲区的数据全部溢出写到磁盘,才恢复向缓冲区写入

  • 后台线程溢写磁盘过程,有以下几个步骤:

    • 先对每个溢写的kv对做分区;分区的个数由MR程序的reduce任务数决定;默认使用HashPartitioner计算当前kv对属于哪个分区;计算公式:(key.hashCode() & Integer.MAX_VALUE) % numReduceTasks

    • 每个分区中,根据kv对的key做内存中排序;

    • 若设置了map端本地聚合combiner,则对每个分区中,排好序的数据做combine操作;

    • 若设置了对map输出压缩的功能,会对溢写数据压缩

  • 随着不断的向环形缓冲区中写入数据,会多次触发溢写(每当环形缓冲区写满100m),本地磁盘最终会生成多个溢出文件

  • 合并溢写文件:在map task完成之前,所有溢出文件会被合并成一个大的溢出文件;且是已分区、已排序的输出文件

  • 小细节:

    • 在合并溢写文件时,如果至少有3个溢写文件,并且设置了map端combine的话,会在合并的过程中触发combine操作;

    • 但是若只有2个或1个溢写文件,则不触发combine操作(因为combine操作,本质上是一个reduce,需要启动JVM虚拟机,有一定的开销)

4.reduce端

  • reduce task会在每个map task运行完成后,通过HTTP获得map task输出中,属于自己的分区数据(许多kv对)

  • 如果map输出数据比较小,先保存在reduce的jvm内存中,否则直接写入reduce磁盘

  • 一旦内存缓冲区达到阈值(默认0.66)或map输出数的阈值(默认1000),则触发归并merge,结果写到本地磁盘

  • 若MR编程指定了combine,在归并过程中会执行combine操作

  • 随着溢出写的文件的增多,后台线程会将它们合并大的、排好序的文件

  • reduce task将所有map task复制完后,将合并磁盘上所有的溢出文件

  • 默认一次合并10个

  • 最后一批合并,部分数据来自内存,部分来自磁盘上的文件

  • 进入“归并、排序、分组阶段”

  • 每组数据调用一次reduce方法

5.总结

  • map端

    • map()输出结果先写入环形缓冲区

    • 缓冲区100M;写满80M后,开始溢出写磁盘文件

    • 此过程中,会进行分区、排序、combine(可选)、压缩(可选)

    • map任务完成前,会将多个小的溢出文件,合并成一个大的溢出文件(已分区、排序)

  • reduce端

    • 拷贝阶段:reduce任务通过http将map任务属于自己的分区数据拉取过来

    • 开始merge及溢出写磁盘文件

    • 所有map任务的分区全部拷贝过来后,进行阶段合并、排序、分组阶段

    • 每组数据调用一次reduce()

    • 结果写入HDFS

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值