MapReduce之combiner的理解

一 Combiner组件意义

有一个文件,总共620M, 有5个数据块,每一个数据块有三个副本,

比如如上图所示,有5台机器,那这文件的数据块分布如图示:

按照InputSplit,那有可能就是5个map任务,而且这5个Map任务很有可能2个或者3个分配同一台机机器运行,这取决于YARN中ContainerAllocator如何分配资源的问题,所以这一台机器可能需要溢写溢写数据到磁盘,每一map任务估计要溢写(128-100*80%)= 48M

那么就有可能溢写很多文件出来;又或者是我们调大了splitSize大小,比如256M,那么我们单个任务需要溢写大小(256-100*80%)=176M

所以Map任务就有可能多出很多输出结果,会有什么问题呢?

Reduce会到对应的节点拷贝map输出结果,如果结果太多,那么势必网络带宽占用的很严重,降低了程序的性能。

有的输出结果其实我们是可以在reduce之前再同一台机器进行一次聚合,这样reduce来拷贝map结果的时候,就可以减少网络I/O,

这个操作就是Combiner。

扫描二维码关注公众号,回复: 13010985 查看本文章

总之一句话:map输出很多的时候,可以现根据key进行一次聚合操作,从而减少reduce 从map端copy数据带来的网络I/O。本质上就是一个map端的reducer

二 Combiner触发时机

时机一:

在我们spill的过程中, 如果设置combiner就会在排序的结果上调用combiner,当然不是什么时候都适合设置Combiner,如果一个分区的数据(key-value)很少,我们不适合去设置Combiner。这个也就是我们以前所说的分组。

时机二:

在map任务可能有很多输出,会溢写很多个文件到磁盘,在map任务结束前,会根据情况合并到一个大的分区,对应的索引文件也会合并。
在这个时候如果我们设置了Combiner,且spill生成的文件数也就是我们对应分区数或者叫numSplil> 我们配置的mapreduce.map.combi

ner.minSpills,在合并之前会再次运行Combiner。 如果spill文件数量太少,没有达到这个值,那么运行Combiner是不划算的,所以则不会调用Combiner。即使我们设置了,也不会调用.

三 是否任意情况下都适合使用Combiner

3.1如果map任务输出很少,就没有必要进行Combiner

3.2Combiner针对汇总统计比较实用,因为Combiner的输出,其实也是Reducer的输入,所以Combiner的出现不应该导致结果不正确

四 代码实现Combiner

public static class IntSumCombinerextends Reducer<Text, IntWritable, Text,IntWritable> {

            private IntWritable result = new IntWritable();

           @Override

           protected void reduce(Text key, Iterable<IntWritable> values,

                      Reducer<Text,IntWritable, Text, IntWritable>.Context context) throws IOException, InterruptedException {

                 if (values == null) {

                      return;

                 }

                 int sum = 0;

                 for (IntWritable value : values) {

                      sum += value.get();

                 }

                 result.set(sum);

                 context.write(key, result);

           }

      }

猜你喜欢

转载自blog.csdn.net/qq_32445015/article/details/108477325