mapreduce作业调优tips

来源:互联网 发布:淘宝衣服拍摄技巧 编辑:程序博客网 时间:2024/05/18 01:25

  这几天一直在优化job,下面是我认为有用的一些tips。

  1. 推测执行在整个集群上关闭,特定需要的作业单独开启,一般可以省下约5%~10%的集群资源。由mapred.map.task.speculative.execution[default true]和mapred.reduce.task.speculative.execution[default true]分别控制map和reduce的推测执行开关。
    mapred.map.task.speculative.execution=true;mapred.reduce.task.speculative.execution=false;
  2. task执行时间很短的时候,关闭推测执行(否则可能会有约5%的task被kill掉,而你会观察到通常kill的是因推测执行而额外启动的tasks)。
  3. 在map时间很长,而map的输出数据并不大的时候,推迟reduce执行时间(否则在推测执行打开的时候会看到有大量的reduce task attempts因过早启动而被kill掉,过早启动会导致集群资源被浪费),这个由mapred.reduce.slowstart.completed.maps[default 0.05,即5%]控制,我甚至看到有的job因为这个kill掉了2*reduceNum以上的task attempts。集群把这个参数设置为0.75应该比较合适。
    mapred.reduce.slowstart.completed.maps=0.80
  4. 当task数量非常多而且通常很短[约1min]的时候,把JVM重用开启,由mapred.job.reuse.jvm.num.tasks[default 1]控制,这通常能获得10%以上的执行时间减少。当节点数量在100个以内,而task数量高达5000以上的时候,可以直接设置为-1[意味着重用个数不限制]。
    mapred.job.reuse.jvm.num.tasks=-1
  5. io.sort.mb被用作map输出的buffer,当buffer使用达到某个阈值的时候会进行sort然后spill到磁盘,默认地io.sort.mb[default 100,即100Mb]通常过小[过小会导致写磁盘次数很多,spill文件也很多],在输出数据量较大的时候建议调整到300左右,建议不要更大,否则sort会很很慢[快排nlogn,先快排后merge的分治手段在大数据情况下更好]。
    io.sort.mb=300
  6. mapred.reduce.parallel.copies控制着reduce从map拉取数据时开启的线程数量[default 5],在输出数据很多,特别是map数量也很多的时候,建议调到15或者更大,否则reduce的copy阶段可能很慢[map已经完成,而reduce还处于远没到33%]。
    mapred.reduce.parallel.copies=15
  7. 对map输出进行压缩可以减少磁盘io和reduce的copy时间,设置为:
      mapred.compress.map.output=true;  mapred.map.output.compression.codec=com.hadoop.compression.lzo.LzoCodec;
  8. 当map输入数据量很大,map个数特别多,但是map执行时间却很短[约1min,通常是因为计算只涉及部分输入数据]的时候,把map的输入分片调大到两倍block大小[default block大小]可能获得更好的执行效率。注意到这可能影响数据本地化的利用,不过我的经验是在这种情况下调大会更好。
    mapred.min.split.size=268435456 
  9. io.sort.factor[default 10]控制着合并spill文件时同时打开的spill文件数量,当spill文件很多时,此值太小会导致需要合并的次数很多,当数据量大的时候应该调高一些。
    io.sort.factor=50
  10. 压缩reduce输出,常用LZO
  11. 下面的参数通常使用默认值,但也可以稍微调节
    mapred.job.shuffle.input.buffer.percent=0.8mapred.job.shuffle.merge.percent=0.8io.sort.spill.percent=0.9#输入数据比较有序时,否则可能导致阻塞map任务输出

通常调节执行参数是写完code之后根据执行情况调节的,如果调节后执行情况还很差,就需要对代码进行优化。

我们可以使用HPROF工具对代码进行性能分析,以便观察各个操作CPU使用情况和内存分配情况,从而针对性地优化,使用HPROF会导致被分析的task执行十分缓慢,因此千万别对所有task都使用分析。

关于HPROF工具的使用,具体见,参看这里。另外是oracle的官方文档,这里:HPROF: A Heap/CPU Profiling Tool 可以了解更多HPROF的内容。


某种程度上说,job的执行效率主要取决于使用的算法。但在实际环境中很多人在写job的时候可能忽略参数调节和性能分析的过程,而导致job运行过慢。这需要一个比较完善的code review规范和监控系统。总的来说,建议对所有job都调节参数,对将长期执行的大型的job进行性能分析优化。