MapReduce性能问题
硬件问题
CPU、内存、网络&&磁盘 IO
使用问题
1)输入文件全是小文件;
2)超大不可切分文件(例如Gzip文件不支持切分;
3)Map 、Reduce的操作数设置不合理;
4)Map运行时间过长,导致Reduce等待时间过长,影响效率;
5)溢写(spill)次数过多,或者合并(merge)文件次数过多;
6)数据倾斜。
优化方法
优化MapReduce需要从数据输入、Map阶段、Reduce阶段、IO传输、数据倾斜五个角度去考虑。
数据输入
1)避免输入大量的小文件,尽可能在执行MapReduce任务前进行小文件的合并。因为大量的小文件会增大切片数生成大量的maptask,增加maptask 的装载次数,浪费内存资源,导致MapReduce运行缓慢;
2)不可避免输入大量小文件时,可以在Diver类中采用CombineTextInputFormat作为输入的InputFormat类,或者自定义InputFormat类改写RecordReader的方式来实现文件的合并1。
//设置InputFormatClass用来合并小文件避免产生很多maptask,降低效率。
job.setInputFormatClass(CombineTextInputFormat.class);
Map阶段
1)减少溢写(spill)的次数,通过调整io.sort.mb及sort.spill.percent参数值,增大触发spill的内存上限,减少spill次数,从而减少磁盘IO;
2)减少合并(merge)的次数,通过调整io.sort.factor参数,增大merge的文件数目,减少merge的次数,从而缩短MR处理时间;
3)在Map端使用combine,减少网络IO。
Reduce阶段
1)调整slowstart.completedmaps参数设置map和reduce共存,当map执行到一定程度,reduce无需等待map可以先运行,减少等待时间;
2)合理设置分区数;
3)尽可能避免Reduce,因为shuffle需要耗费大量的网络和磁盘IO,影响效率;
4)通过调整mapred.job.reduce.input.buffer.percent参数合理设置Reduce端的Buffer,可以避免一些不必要的溢出写盘,再读盘的磁盘IO消耗,可以直接将一部分数据直接通过内存交给Reduce去处理。
IO传输
1)使用压缩文件,减少网络IO;
2)使用SequenceFile二进制文件。
数据倾斜
1)通过多原数据进行抽样分析来预设分区边界值;
2)在Map端做Combine做数据聚合减少Reduce端压力并且减少网络IO;
3)通过自定义分区来分配数据的分布,避免数据倾斜;
4)尽可能避免在Reduce端Join,用Map端Join替代。
常用调优参数
配置文件 | 配置参数 | 参数说明 |
---|---|---|
mapred-default.xml | mapreduce.map.memory.mb | 默认1024 一个Map Task可使用的资源上限(单位:MB)如果Map Task实际使用的资源量超过该值,则会被强制杀死。 |
mapred-default.xml | mapreduce.reduce.memory.mb | 默认1024 一个Reduce Task可使用的资源上限(单位:MB)如果Map Task实际使用的资源量超过该值,则会被强制杀死。 |
mapred-default.xml | mapreduce.map.cpu.vcores | 默认1 每个Map task可使用的最多cpu core数目。 |
mapred-default.xml | mapreduce.reduce.cpu.vcores | 默认1 每个Reduce task可使用的最多cpu core数目。 |
mapred-default.xml | mapreduce.reduce.shuffle.parallelcopies | 默认5 每个reduce去map中拿数据的并行数。 |
mapred-default.xml | mapreduce.reduce.shuffle.merge.percent | 默认0.66 一buffer中的数据达到多少比例开始写入磁盘。 |
mapred-default.xml | mapreduce.reduce.shuffle.input.buffer.percent | 默认0.7 buffer大小占reduce可用内存的比例。 |
mapred-default.xml | mapreduce.reduce.input.buffer.percent | 默认0.0 指定多少比例的内存用来存放buffer中的数据。 |
yarn-default.xml | yarn.scheduler.minimum-allocation-mb | 默认1024 给应用程序container分配的最小内存。 |
yarn-default.xml | yarn.scheduler.maximum-allocation-mb | 默认8192 给应用程序container分配的最大内存。 |
yarn-default.xml | yarn.scheduler.minimum-allocation-vcores | 默认1 每个container申请的最小CPU核数。 |
yarn-default.xml | yarn.scheduler.maximum-allocation-vcores | 默认32 每个container申请的最大CPU核数。 |
yarn-default.xml | yarn.nodemanager.resource.memory-mb | 默认8192 给containers分配的最大物理内存。 |
mapred-default.xml | mapreduce.task.io.sort.mb | 默认100M shuffle的环形缓冲区大小。 |
mapred-default.xml | mapreduce.map.sort.spill.percent | 默认80% 环形缓冲区溢出的阈值。 |