MapReduce之Shuffle详解

Hadoop原生的计算框架MapReduce,简单概括一下:进程量级很重,启动很慢,但能承载的数据量很大,效率相较于Spark微批处理和Flink实时来讲很慢,Shuffle任何一个写MR同学都必须掌握的东西,说难不难,说简单也不简单

MapReduce程序的五个阶段:

  • input
  • map
  • shuffle
  • reduce
  • output

我将Shuffle阶段加粗了,原因很简单,因为这里很重要

1. 关于Shuffle过程实现的功能:

1. 分区:

  • 决定当前的Key交给哪个Reducer进行处理,相同的Key则由相同的Reducer处理
  • 默认是根据Key的Hash值,对Reduce个数取余(源码如下)
    public int getPartition(K2 key, V2 value, int numReduceTasks) {
          return (key.hashCode() & Integer.MAX_VALUE) % numReducTasks  
    }

     

2. 分组

  • 将相同的Key的value进行合并
  • Key相等时将分到同一个组里面
  • MapReduce阶段,一行调用一次Map方法,一种Key调用一次Reduce

3. 排序:将Key按照字典排序

 

2. 关于Shuffle过程实现功能的详细描述:

1. Map端Shuffle:
  1. Spill:溢写
    1. 每一个Map处理之后的结果都会进入环形缓冲区(内存,默认100M)(关于环形缓冲区有必要单独了解一下,不详细展开了)
    2. 分区:对每一条key-value进行分区,打标签
    3. 排序:将相同分区的数据进行分区内排序
    4. 当环形缓冲区达到阈值的80%,将分区排序后的数据写到磁盘变成文件,最终会生成多个小文件,
  2. Merge合并:
    1. 将spill生成的小文件进行合并
    2. 将相同分区的数据进行排序
  3. Map task结束)通知ApplicationMaster,Reduce主动过来拉取数据Reduce端Shuffle

2. Reduce端Shuffle:

  1. 启动多个线程,去每台机器上拉去属于自己分区的M数据
  2. Merge:
    1. 将每个Maptask的结果属于自己分区的数据进行合并
    2. 将整体属于自己分区的数据进行排序
  3. 分组:对相同的key的value进行合并

 

3. 关于MapReduce的Shuffle优化:

MapReduce Shuffle过程的优化:
  1. Combiner:合并
    1. 在map阶段提前进行了一次合并,一般来说等同于提前进行了reduce,降低reduce的压力
    2. 不是所有的程序都适合combiner
  2. Compress:压缩
    1. 能大大减少磁盘和网络的IO
  3. hadoop中设置压缩:
    1. hadoop checknative查看本地支持哪些压缩
    2. 常见的压缩格式:snappy,lzo,lz4
    3. 修改本地支持的压缩方式:替换lib/native
  4. MapReduce程序可以设置压缩的位置:
    1. 输入
    2. map的中间结果(需要同时指定)
      1. mapreduce.map.output.compress
      2. mapreduce.map.output.compress.codec=默认是DefaultCodec
    3. reduce的输出
      1. mapreduce.output.fileoutputformat.compress
      2. Mapreduce,output.fileoutputformat.compress.codec
  5. 怎么设置压缩:
    1. 集群配置文件内
    2. 设置conf对象当前程序有效
    3. 运行时指定参数: -Dmapreduce.output.fileoutputformat.compress=true ….

 

posted @ 2020-07-15 13:37  wen1995  阅读(302)  评论(0编辑  收藏  举报