5.3.2 设计思路

这个实例仅仅要求对输入数据进行排序,熟悉MapReduce过程的读者很快会想到在MapReduce过程中就有排序。是否可以利用这个默认的排序、而不需要自己再实现具体的排序呢?答案是肯定的。但是在使用之前首先要了解MapReduce过程中的默认排序规则。它是按照key值进行排序,如果key为封装int的IntWritable类型,那么MapReduce按照数字大小对key排序;如果key为封装String的Text类型,那么MapReduce按照字典顺序对字符串排序。需要注意的是,Reduce自动排序的数据仅仅是发送到自己所在节点的数据,使用默认的排序并不能保证全局的顺序,因为在排序前还有一个partition的过程,默认无法保证分割后各个Reduce上的数据整体是有序的。所有要想使用默认的排序过程,还必须定义自己的Partition类,保证执行Partition过程之后所有Reduce上的数据在整体上是有序的,然后再对局部Reduce上的数据进行默认排序,这样才能保证所有数据有序。了解了这个细节,我们就知道,首先应该使用封装int的IntWritable型数据结构,也就是将读入的数据在Map中转化成IntWritable型,然后作为key值输出(value任意);其次需要重写partition类,保证整体有序,具体做法是用输入数据的最大值除以系统partition数量的商作为分割数据的边界增量,也就是说分割数据的边界为此商的1倍、2倍至numPartitions-1倍,这样就能保证执行partition后的数据是整体有序的;然后Reduce获得<key, value-list>之后,根据value-list中元素的个数将输入的key作为value的输出次数,输出的key是一个全局变量,用于统计当前key的位次。需要注意的是,这个程序中没有配置Combiner,也就是说在MapReduce过程中不使用Combiner。这主要是因为使用Map和Reduce就已经能够完成任务了。

由于此程序简单且执行步骤与单词计数实例完全相同,所以不再赘述,下面只给出程序。