
# MapReduce Shuffle调优
#### 操作场景
Shuffle阶段是MapReduce性能的关键部分，包括了从Map task将中间数据写到磁盘一直到Reduce task复制数据并最终放到reduce函数的全部过程。这部分Hadoop提供了大量的调优参数。
图1Shuffle过程   
![](https://support.huaweicloud.com/cmpntguide-lts-mrs/zh-cn_image_0000001724867225.png "点击放大")
#### 操作步骤
1. **Map阶段的调优**
   - 判断Map使用的内存大小 判断Map分配的内存是否足够，一个简单的办法是查看运行完成的job的Counters中，对应的task是否发生过多次GC，以及GC时间占总task运行时间之比。通常，GC时间不应超过task运行时间的10%，即GC time elapsed (ms)/CPU time spent (ms)\<10%。
     主要通过如下参数进行调整。
     参数入口：
     进入Yarn服务参数"全部配置"界面，在搜索框中输入参数名称。具体操作请参考[修改集群服务配置参数](https://support.huaweicloud.com/cmpntguide-lts-mrs/mrs_01_2125.html)章节。
     建议：配置"mapreduce.map.java.opts"参数中"-Xmx"值为"mapreduce.map.memory.mb"参数值的0.8倍。
     表1参数说明 
     | **参数**                  | **描述**                                                                                                                        | **默认值**                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
     |:---|:---|:---|
     | mapreduce.map.memory.mb | map任务的内存限制。                                                                                                                   | 4096                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
     | mapreduce.map.java.opts | map子任务的JVM参数。如果设置，会替代mapred.child.java.opts参数；如果未设置-Xmx，Xmx值从mapreduce.map.memory.mb\*mapreduce.job.heap.memory-mb.ratio计算获取。 | - 集群已开启Kerberos认证：-Djava.net.preferIPv4Stack=true -Djava.net.preferIPv6Addresses=false -Djava.security.krb5.conf=*${BIGDATA_HOME}* /common/runtime/krb5.conf -Dbeetle.application.home.path=*${BIGDATA_HOME}/*common/runtime/security/config  - 集群未开启Kerberos认证：-Djava.net.preferIPv4Stack=true -Djava.net.preferIPv6Addresses=false -Dbeetle.application.home.path=*${BIGDATA_HOME}*/common/runtime/security/config   |
        
     
   
   - 使用Combiner 在Map阶段，有一个可选过程，将同一个key值的中间结果合并，叫做Combiner。一般将reduce类设置为Combiner即可。通过Combiner，一般情况下可以显著减少Map输出的中间结果，从而减少shuffle过程的网络带宽占用。可通过如下接口为一个任务设置Combiner类。
     表2Combiner设置接口 
     | **类名**                          | **接口名**                                                      | **描述**             |
     |:---|:---|:---|
     | org.apache.hadoop.mapreduce.Job | public void setCombinerClass(Class\<? extends Reducer\> cls) | 为Job设置一个Combiner类。 |
        
     
    
2. **Copy阶段的调优**
   数据是否压缩：
   对Map的中间结果进行压缩，当数据量大时，会显著减少网络传输的数据量，但是也因为多了压缩和解压，带来了更多的CPU消耗。因此需要做好权衡。当任务属于网络瓶颈类型时，压缩Map中间结果效果明显。针对bulkload调优，压缩中间结果后性能提升60%左右。
   配置方法：将"mapreduce.map.output.compress"参数值设置为"true"，将"mapreduce.map.output.compress.codec"参数值设置为"org.apache.hadoop.io.compress.SnappyCodec"。
   
3. **Merge阶段的调优**
   通过调整如下参数减少reduce写磁盘的次数。
   参数入口：
   进入Yarn服务参数"全部配置"界面，在搜索框中输入参数名称。具体操作请参考[修改集群服务配置参数](https://support.huaweicloud.com/cmpntguide-lts-mrs/mrs_01_2125.html)章节。
   表3参数说明 
   | **参数**                                        | **描述**                                                                               | **默认值** |
   |:---|:---|:---|
   | mapreduce.reduce.merge.inmem.threshold        | 内存合并进程的文件数阈值。累计文件数达到阈值时会发起内存合并及溢出到磁盘。小于等于0的值表示该阈值不生效且仅基于ramfs的内存使用情况来触发合并。           | 1000    |
   | mapreduce.reduce.shuffle.merge.percent        | 发起内存合并的使用率阈值，表示为分配给映射输出信息的内存的比例（是由mapreduce.reduce.shuffle.input.buffer.percent设置的）。 | 0.66    |
   | mapreduce.reduce.shuffle.input.buffer.percent | shuffle过程中分配给映射输出信息的内存占最大堆大小的比例。                                                     | 0.70    |
   | mapreduce.reduce.input.buffer.percent         | Reduce过程中保存映射输出信息的内存相对于最大堆大小的比例。当shuffle结束时，需保证reduce开始前内存中所有剩余的映射输出信息所使用的内存小于该阈值。   | 0.0     |
      
   
 
