常规的MapReduce模型由mapper和reducer组成,mapper的输出按照键排序,作为reducer的输入。combiner的作用是在mapper和reducer之间增加一个中间层,举一个例子:
对于key为1950,有两个mapper,mapper1输出:
1950 10
1950 20
1950 30
mapper2输出:
1950 40
1950 50
那么reducer的输入是(1950,[10,20,30,40,50]),设置规则为选择最大值,最终输出为(1950,50)
增加combiner之后,mapper1和mapper2先将数据输入combiner选择最大值,然后combiner的输出进入reducer作为输入,即reducer的输入为(1950,[30,50]),这里combiner的逻辑和reducer的逻辑一样,都是选择最大值,因此不用为combiner单独编写一套流程,只要修改作业运行函数即可,如下:
public class MaxTemperatureWithCombiner {
public static void main(String[] args) throws Exception {
if (args.length != 2)
System.exit(-1);
Job job = new Job();
job.setJarByClass(MaxTemperatureWithCombiner.class);
job.setJobName("MaxTemperatureWithCombiner");
FileInputFormat.addInputPath(job, new Path(args[0]));
FileOutputFormat.setOutputPath(job, new Path(args[1]));
job.setMapperClass(MaxTemperatureMapper.class);
/* 设置combiner,这里直接复用reducer的逻辑 */
job.setCombinerClass(MaxTemperatureReducer.class);
job.setReducerClass(MaxTemperatureReducer.class);
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(IntWritable.class);
System.exit(job.waitForCompletion(true) ? 0 : 1);
}
}
最终运行结果显然和没有combiner是一样的。combiner的使用有限制,这里是选择最大值,因此可以加combiner,但是若是求平均数,那么不能加combiner,因为对两个局部求平均之后再求平均显然无法得到正确的结果