一、Job执行三原则
1.1 原则一 充分利用集群资源
尽量让所有节点都有任务处理,这样能尽量保证集群资源被充分利用,任务的并发度达到最大。可以通过调整处的数据量大小,以及调整map和reduce任务数量。
Reduce的个数控制通过:“mapreduce.job.reduces”
Map的个数取决于使用了哪种InputFormat,默认的TextFileInputFormat将根据block的个数来分配map个数(一个block一个map)。
1.2 原则二 reduce阶段尽量放在一轮
努力避免以下场景:
1.观察Job如果大多数reducetask在第一轮运行完成后,剩下很少甚至一个reducetask刚开始运行。这种情况下这个reducetask的运行时间决定了该Job的运行时间。可以考虑将reduce数量减少。
2.观察Job运行情况,如果maptask运行完成后,只有个别节点有reducetask在运行。这个时候集群资源没有得到充分利用,需要增加reducetask的并行度以便每个节点都有任务处理。
1.3 原则三 每个task执行时间要合理
一个Job中,每个maptask和reducetask的执行时间只有几秒钟,这就意味着这个Job的大部分时间都消耗在task调度和启停上了,因此可以考虑增加每个task处理的数据大小。建议一个task处理时间为1分钟。
二、Shuffle调优
2.1 Map阶段
2.1.1 判断Map内存使用
判断map分配的内存是否够用,可以查看运行完的job的Counter中(历史服务器)对应的task是否发生多次GC,以及GC时间占总task运行时间之比。通常,GC时间不应该超过task运行时间10%(GC time elapsed (ms)/CPU time spent (ms)<10%)。
Map阶段需要的内存还需要随着环形缓冲区的调大而对应调整:
mapreduce.map.memory.mb (默认1024)
Map需要的CPU核数需要通过以下参数调整:
mapreduce.map.memory.mb (默认1024)
如果资源充沛,建议调整如下:
mapreduce.map.memory.mb=3G(默认1G)
mapreduce.map.cpu.vcores=1(默认也是1)
环形缓冲区:(Map方法执行后首先把数据写入环形缓冲区,为什么MR框架选择先写内存而不是直接写磁盘?这样的目的主要是为了减少磁盘i/o)
环形缓冲默认100M(mapreduce.task.io.sort.mb),
当到达80%(mapreduce.map.sort.spill.percent)时就会溢写磁盘。
每达到80%都会重写溢写到一个新的文件。
当集群内存资源充足,考虑增大mapreduce.task.io.sort.mb提高溢写的效率,而且会减少中间结果的文件数量。
调整mapreduce.task.io.sort.mb=512M。
当文件溢写完后,会对这些文件进行合并,
默认每次合并10(mapreduce.task.io.sort.factor)个溢写的文件,
建议调整 mapreduce.task.io.sort.factor=64。这样可以提高合并的并行度,减少合并的次数,降低对磁盘操作的次数。
2.1.2 Combiner
在Map阶段有一个可选的过程,将同一个key值的中间结果合并,叫做Combiner。(一般将Reduce类作为Combiner即可)
通过Combiner一般情况下可以明显减少Map输出的中间结果,从而减少Shuffle过程网络宽带的占用。
建议:不影响最终结果的情况下,加上Combiner!
2.2 Copy阶段
对Map的中间结果进行压缩,当数据量大时,会显著减少网络传输的数据量。
但是也因为多了压缩和解压,带来了更多的CPU消耗。因此需要做好权衡。当任务属于网络瓶颈类型时,压缩Map中间结果效果明显。
在实际经验中Hadoop的运行的瓶颈一般都是IO而不是CPU,压缩一般可以1