二次排序(在实际生产中用得到,会提高效率)
Mapreduce框架在记录到达reducers之前,对记录按照key进行排序。对于任何部分key,值都是未排序的。值出现的顺序,甚至都不是稳定的从一个到另一个,因为,这些值来自不同的map tasks,这些tasks可能在不同的时间结束。通常来说,大多数Mapreduce程序的编写不依靠值在reduce函数出现的顺序。但是,通过,以特定的方法,分组和排序key,来利用排好序的value,这是可行的。
为了说明这一观点,请看以下的情况。Mapred程序计算每年温度的最高值。如果我们把每年的温度,都降序排列,那么,我们就不必遍历这些值来找出最大值了,我们可以拿出每一年的最大值,而忽略掉其它的值。
为了实现这个需求,我们改变keys为组合数,year和temperature的组合。我们想让这个组合key的排序是先按照year升序排列,在按照temperature降序排列。
1900 35°C
1900 34°C
1900 34°C
...
1901 36°C
1901 35°C
如果,我们做的所有事情只是改变key,那么,这时还是不能帮助我们,因为,每年的记录不会走向相同的reducer,因为,他们有不同的keys。例如,(1900, 35°C) and (1900, 34°C) 会进入不同的reducers。设置一个partitioner 来分组key的一部分(即year),我们可以保证相同年份的记录会进入相同的reducer。这仍然不足以达到我们的目标。partitioner 可以确保reducer接受每年的所有记录;但是,他并不改变这样一个事实,在分割中,reducer是以key分组的。(译者注:如下图)
难题的最后一步是,设置分组的控制。如果,我们在reducer中根据key中的year来分组values,那么,我们会发现所有的相同年的记录会在一个reduce分组中。并且,因为它们是按照temperature降序排列的,第一个值就是最大值。
总结如下,按照value排序的菜谱如下:
1、把原来的key和value组合成新的key。
2、Key比较器应该按照组合key来排序,也就是原来的key和value。
3、partitioner 和组合key的grouping 比较器,应该只以原来的key进行分割和分组。