MapReduce优化方法主要从六个方面考虑:数据输入、Map阶段、Reduce阶段、IO传输、数据倾斜问题和常用的调优参数。
数据输入
合并小文件
在数据输入map()之前,使用CombineTextInputFormat进行小文件合并,可有效减少切片数量和MapTask数量。
Map阶段
1.自定义分区
通过自定义类继承Partitioner接口,重写getPartition()方法,可以实现数据自定义分流,减少ReduceTask压力。
2.减少数据溢写的次数
2.1 扩大环形缓冲区的内存,
mapreduce.task.io.sort.mb
Shuffle的环形缓冲区大小默认为100M,可以扩大至200M(以200M为例);
2.2 增大溢写阈值
mapreduce.map.sort.spill.percent
环形缓冲区溢出的阈值默认为80%,可以提升至90%(预留大概20M进行方向溢写);
3.在不影响最终业务逻辑的前提下,适当使用Combiner进行预聚合
job.setCombinerClass(xxxReducer.class);
4.增加每次Merge合并次数
mapreduce.task.io.sort.factor
默认为10(一次合并处理10个溢写文件),可以改成20;
5.减少磁盘IO,可以采用Snappy(最优)/LZO进行数据压缩
conf.setBoolean("mapreduce.map.output.compress",true);
conf.setClass("mapreduce.map.output.compress.codec",SnappyCode.class,CompressionCodec.class);
6.其他
扩大MapTask内存---mapreduce.map.memory.mb(默认为1GB);
增加CPU核数---mapreduce.map.cpu.vcores(默认MapTask的CPU核数为1);
增加异常重试次数---mapreduce.map.maxattempts(每个MapTask最大重试次数,默认为4);
Reduce阶段
1.提高每个Reduce去Map中拉取数据的并行数
mapreduce.reduce.shuffle.parallelcopies
Reduce的Copy阶段,每个ReduceTask拷贝Map分区结果数据时,同时访问的分区数,默认值为5,可以提高至10;
2.提高Reduce中Buffer所占内存的比例
mapreduce.reduce.shuffle.input.buffer.percent
表示ReduceTask在copyMap中的数据至内存时,可以存储的内存大小比例,默认值为0.7,可以提升至0.8;
3.上调Buffer中数据溢写阈值
mapreduce.reduce.shuffle.merge.percent
该值表示Buffer中内存存储的数据大小达到整体内存(整个ReduceTask)的比例时,开始写入磁盘,默认值为0.66,可以提升至0.75(该值可随ReduceTask整体内存大小而动态设置其比例,大概区间为2/3~0.8);
4.降低ReduceTask提前申请资源的MapTask完成比例
mapreduce.job.reduce.slowstart.completedmaps
当MapTask完成的比例达到该值后,MrAppMaster会提前给ReduceTask申请资源,默认值为0.05,可以调低至0.01;
5.延长Task超时时间
mapreduce.task.timeout
如果一个Task在一定时间内没有任何进入,既不会读取新的数据,也没有输出数据,则认为该Task处于Block状态,可能是卡住了,也许永远会卡住,为了防止因为用户程序永远Block住不退出,则强制设置了一个超时时间(单位毫秒),默认值为600000(10分钟)。
如果你的程序对每条输入数据的处理时间过长,建议将该参数调大。
6.其他
扩大ReduceTask内存---mapreduce.reduce.memory.mb(默认为1GB);
增加CPU核数---mapreduce.reduce.cpu.vcores(默认ReduceTask的CPU核数为1);
增加异常重试次数---mapreduce.reduce.maxattempts(每个ReduceTask最大重试次数,默认为4);
数据倾斜问题
数据倾斜的现象
①数据频率倾斜:某一个区域的数据量要远大于其他区域;
②数据大小倾斜:部分记录的大小远远大于平均值;
减少数据倾斜的方法
1.预测
可以通过对原始数据进行抽样,根据其结果集来预设分区边界值。
2.打散
可以使数据随机均匀打散至不同的分区;也可以使用自定义分区,根据输出键的特点进行特定分区。
3.预聚合
通过Combiner进行预聚合,从而精简数据,减少数据倾斜。