hadoop 0.20.2 api里面,作业被重新定义到了类 org.apache.hadoop.mapreduce.Job。
它有3个特别的方法:
job.setPartitionerClass(Partitioner p);
job.setSortComparatorClass(RawComparator c);
job.setGroupingComparatorClass(RawComparator c);
数据在被map处理过之后,会根据 Partitioner 定义的规则,把中间结果分发到特定的reduce。
Partitioner<Key, Value> 包含一个方法:public int getPartition(Key k, Value v, int parts)
public static class P extends Partitioner<IdWithTimestamp, Value> {
@Override
public int getPartition(IdWithTimestamp k, Value v, int parts) {
int hash = k.getId().hashCode();
return (hash & Integer.MAX_VALUE) % parts;
}
}
接下来,可以做一些控制,使得不同 Key的中间数据,能够被分发到同一个reduce 处理,setGroupingComparatorClass提供分组规则。
例如,key可能是[id, timestamp],这样可以使相同的id(String)能按时间戳(long)排序,现在拆出包含在key里的相同id,分到相同的组。
Java代码
然后,中间数据在被reduce处理之前,会先被集中排序,setSortComparatorClass提供排序规则。
Java代码public class TimestampComparator extends TextComparator {
@Override
public int compare(IdWithTimestamp o1, IdWithTimestamp o2) {
return o1.getTimestamp() - o2.getTimestamp();
}
}
如果不提供这些东西,默认使用的是 Key类型的 compareTo方法,而不是 hashCode和 equals。
实际上说的比较明白就是,Partitioner 负责把任务调度到对应的跑reduce的机器上,但是一个机器可能会反复调用多次reduce函数。而group comparator 决定了哪些key放在一个reduce函数里。
最后说明的是,sort comparator 决定着一个group里的数据该以什么样的顺序进入到reduce函数中。
利用这个特性,可以对复合键进行筛选排序。最后举一个例子:
假设 通过Partitioner 分到某一个reduce机器上的数据如下
key value
[a,1] 1
[a,2] 2
[b,1] 1
[b,2] 2
我想通过key里的第一部分来分reduce函数,通过第二部分排序。
reduce 输入函数为
key value list
[a,1] 1 、2
[b,1] 1、2
由于我利用了 value和key的第二部分相同的特性,所以value list里也是排好顺序的。