Partitioner, SortComparator and GroupingComparator in Hadoop

来源:互联网 发布:亚洲四小龙知乎 编辑:程序博客网 时间:2024/05/11 03:03

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)

Java代码  
  1. public static class P extends Partitioner<IdWithTimestamp, Value> {   
  2.   
  3.     @Override  
  4.     public int getPartition(IdWithTimestamp  k, Value v, int parts) {   
  5.         int hash = k.getId().hashCode();   
  6.         return (hash & Integer.MAX_VALUE) % parts;   
  7.     }   
  8.   
  9. }  

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代码  
  1. public class IdComparator extends TextComparator {   
  2.   
  3.     @Override  
  4.     public int compare(IdWithTimestamp o1, IdWithTimestamp o2) {   
  5.         return o1.getId().compareTo(o2.getId());   
  6.     }   
  7.   
  8. }  
public class IdComparator extends TextComparator { @Override public int compare(IdWithTimestamp o1, IdWithTimestamp o2) { return o1.getId().compareTo(o2.getId()); }}

 

然后,中间数据在被reduce处理之前,会先被集中排序,setSortComparatorClass提供排序规则。

Java代码  
  1. public class TimestampComparator extends TextComparator {   
  2.   
  3.     @Override  
  4.     public int compare(IdWithTimestamp o1, IdWithTimestamp o2) {   
  5.         return o1.getTimestamp() - o2.getTimestamp();   
  6.     }   
  7.   
  8. }   

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里也是排好顺序的。