Map方法之后,Reduce方法之前的数据处理过程称之为Shuffle。

具体Shuffle过程详解: (1)MapTask收集我们的map()方法输出的kv对,放到内存缓冲区中 (2)从内存缓冲区不断溢出本地磁盘文件,可能会溢出多个文件 (3)多个溢出文件会被合并成大的溢出文件 (4)在溢出过程及合并的过程中,都要调用Partitioner进行分区和针对key进行排序 (5)ReduceTask根据自己的分区号,去各个MapTask机器上取相应的结果分区数据 (6)ReduceTask会取到同一个分区的来自不同MapTask的结果文件,ReduceTask会将这些文件再进行合并(归并排序) (7)合并成大文件后,Shuffle的过程就结束了,后面进入ReduceTask的逻辑运算过程(从文件中取出一个一个的键值对Group,调用用户自定义的reduce()方法) 注意:shuffle中的缓冲区大小会影响到MapReduce程序的执行效率,原则上说,缓冲区越大磁盘io的次数越少,执行速度就越快。 缓冲区的大小可以通过参数调整,参数:io.sort.mb默然100M 优化 1.Map阶段 (1)增大环形缓冲区大小,有100M扩大到200M (2)增大环形缓冲区溢写的比例,由80%扩大到90% (3)减少对溢写文件的merge次数。 (4)不影响实际业务的前提下,采用Combiner提前合并,减少I/O 2.Reduce阶段 (1)合理设置Map和Reduce数:两个都不能设置太少,也不能设置太多。太少,会导致Task等待,延长处理时间;太多,会导致Map、Reduce任务间竞争资源,造成处理超时等错误。 (2)设置Map/Reduce共存:调整slowstart.completedmaps参数,使Map运行到一定程度后,Reduce也开始运行,减少Reduce的等待时间。 (3)规避使用Reduce,因为Reduce在用于连接数据量集的时候将会产生大量的网络消耗。 (4)增加每个Reduce去Map中拿数据的并行数。 (5)集群性能可以的前提下,增大Reduce端存储数据内存的大小。 3)IO传输 采用数据压缩的方式,减少网络IO的的时间。安装Snappy和LZOP压缩编码器。 压缩: (1)map输入端主要考虑数据量大小和切片,支持切片的有Bzip2、LZO。注意:LZO要想支持切片必须创建索引; (2)map输出端主要考虑速度,速度快的snappy、LZO; (3)reduce输出端主要看具体需求,例如作为下一个mr输入需要考虑切片,永久保存考虑压缩率比较大的gzip。 4)整体 (1)NodeManager默认内存8G,需要根据服务器实际配置灵活调整,例如128G内存,配置为100G内存左右,yarn.nodemanager.resource.memory-mb。 (2)单任务默认内存8G,需要根据该任务的数据量灵活调整,例如128m数据,配置1G内存,yarn.scheduler.maximum-allocation-mb。 (3)mapreduce.map.memory.mb :控制分配给MapTask内存上限,如果超过会kill掉进程(报:Container is running beyond physical memory limits. Current usage:565MB of512MB physical memory used;Killing Container)。默认内存大小为1G,如果数据量是128m,正常不需要调整内存;如果数据量大于128m,可以增加MapTask内存,最大可以增加到4-5g。 (4)mapreduce.reduce.memory.mb:控制分配给ReduceTask内存上限。默认内存大小为1G,如果数据量是128m,正常不需要调整内存;如果数据量大于128m,可以增加ReduceTask内存大小为4-5g。 (5)mapreduce.map.java.opts:控制MapTask堆内存大小。(如果内存不够,报:java.lang.OutOfMemoryError) (6)mapreduce.reduce.java.opts:控制ReduceTask堆内存大小。(如果内存不够,报:java.lang.OutOfMemoryError) (7)可以增加MapTask的CPU核数,增加ReduceTask的CPU核数 (8)增加每个Container的CPU核数和内存大小 (9)在hdfs-site.xml文件中配置多目录(多磁盘) (10)NameNode有一个工作线程池,用来处理不同DataNode的并发心跳以及客户端并发的元数据操作。dfs.namenode.handler.count=图片: https://uploader.shimo.im/f/IM1hShcaGURul0U4.png,,比如集群规模为8台时,此参数设置为41。可通过简单的python代码计算该值,代码如下。
[hadoop@hb ~]$ python
Python 2.7.5 (default, Apr 11 2018, 07:36:10)
[GCC 4.8.5 20150623 (Red Hat 4.8.5-28)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import math
>>> print int(20*math.log(8))
41
>>> quit()