hadoop groupingComparator 与 secondary sort

来源:互联网 发布:自动化办公软件下载 编辑:程序博客网 时间:2024/05/07 18:55

《hadoop权威指南》里的例子:有许多气象记录,需要找出每年的最高温度,通过secondary sort实现。(这个任务其实没有必要使用secondary sort,这里只是为了演示)

map-reduce的shuffle阶段,只会根据key进行排序,而同一个key的value是无序的,所以要把年份和温度都放在key里面。map的输出:key为year-temperature pair,value为null。job的partitioner设为根据年份进行hash(将同一年份的数据发送到同一个reducer)。job的sortComparator根据年份和温度进行比较。job的groupingComparator只根据年份进行比较。完整代码在此。

reducer的代码很简单,只有一行:将key写出即可。输出就是每个年份以及当年的最高气温。

void reduce(IntPair key, Iterable<NullWritable> values, Context context) {    context.write(key, NullWritable.get());}

groupingComparator的作用是什么?书中对此语焉不详,只说将相同年份的数据分到一组。网上的解释也大多是错误的。

误解:reducer会根据groupingComparator对数据进行排序。略一思考就会发现这不合逻辑,如果reduce需要排序的话,那么map阶段的排序就没有必要了,反正到了reducer这里还会被打乱。

hadoop官方文档对groupingComparator的解释是:controls which keys are grouped together for a single call to Reducer.reduce()。那么到底是如何control的呢?看下面的例子。

样本数据如下,第一列是key,第二列是value。

1 124 415 528 821 111 138 838 815 515 534 434 42

比较一下三种操作的输出:

不指定groupingComparator:1:12,11,13,4:41,43,42,5:52,51,53,8:82,83,81,指定Less5GroupComparator,即将小于5的key分为一组,其余一组:1:12,11,13,41,43,42,5:52,51,53,82,83,81,指定Sum9GroupComparator,即相加等于9的key分为一组:1:12,11,13,4:41,43,42,52,51,53,8:82,83,81,

代码如下:

从第一组输出可以看到:数据已经按key排序,同一个key里的value是无序的。另外可以推测,mapper使用的排序算法是稳定的,因为同一个key的values的顺序与输入相同。

第二组输出已经正确地将数据分成了两组,并且每一组的key是该组里面key的第一个值。(即key为1和5,而不是4和8)

第三组,key为4和5的已经正确地归为了一组,但是1和8呢。实际上goupingComparator并不进行任何排序操作,只是依次取出reducer收到的key-value对,然后比较当前key与前一个key,如果比较的结果为0,就认为是同一个group,对同一个group里的数据进行一次reduce调用。

org.apache.hadoop.mapreduce.Reducer的实现已经明白无误地说明了这一点:

另外,如果不设置groupingComparator的话,使用的就是map阶段排序用的comparator。

// org.apache.hadoop.mapreduce.Jobpublic RawComparator getOutputValueGroupingComparator() {Class<? extends RawComparator> theClass = getClass(JobContext.GROUP_COMPARATOR_CLASS, null, RawComparator.class);if (theClass == null) {return getOutputKeyComparator();}return ReflectionUtils.newInstance(theClass, this);}
0 0
原创粉丝点击