最近跑一个Hadoop程序,处理一年的log,处理的时候发现Map有18000多个,Reduce任务数我设置了1000个。
最后半个小时过去了,所有Map都执行完毕,就有一个Reduce没有结束,然后没管他继续干其他的了。
两个小时过去了,这个Reduce一开还是处于copy阶段,进度10%,受不了,直接kill掉,看日志,没有问题啊,5个fetch都正常,就是网络好慢。以为是数据量太大了,Reduce数太小了,最后取了一个月的数据,1000个reduce,还是一样。
最后定位到网络,明明自己的网络很快,显示的却是1M/s,每次取那么点数据?分析程序,发现Combiner这个类被我不小心注释掉了
job.setCombinerClass(MyReducer.class);
combiner就是在map输出阶段,小范围的执行“Reduce任务”,没有加上,所以Reduce任务在copy阶段copy的“碎片”比较多
其次,由于我处理Reduce结果输出的编码,所以在设置combiner类的时候,不能直接用Reduce类,稍微改一下,将combiner继承Reduce类,但是在combiner中不要转码
public class MyCombiner extends Reducer<Text, LongWritable, Text, LongWritable> {
private LongWritable result = new LongWritable();
public void reduce(Text key, Iterable<LongWritable> values,Context context) throws IOException, InterruptedException {
long sum = 0;
for (LongWritable val : values) {
sum += val.get();
}
result.set(sum);
// context.write(new Text(key.toString().getBytes("GB18030")), result);//Reduce中这样写
context.write(key, result);
}
}