人们对于Mapreduce程序刚开始时都认为只需要一个reduce就够了。毕竟,在你处理数据之前一个reducer已经把数据都分好类了,有谁不喜欢分好类的数据呢。但是这样我们就忽略了并行计算的优势。如果只有一个reducer,我们的云计算就退化成了一个小雨点。
在多个reducer的情况下,我们需要某种机制来控制mapper的结果的分配问题。这是就Partitioner的工作了。
在默认情况下,hadoop通过比较key的hash值来分配,默认使用HashPartitioner。
有时默认的功能不能满足我们的要求,比如我们以前自定义的Edge类(http://blog.csdn.net/on_way_/article/details/8589187)。当我们想要知道每个机场乘客起飞的数量时。我们有如下数据
(北京, 上海) 张三
(北京, 青岛) 李四。。。。。。。
如果我们用HashPartitioner来分配,那么这两行就会被送往不同的reducer上,机场起飞的数量就会被算两次,而且每次都是错误的。
我们需要为我们的应用程序定制一个partitioner。
import org.apache.hadoop.io.Writable; import org.apache.hadoop.mapred.JobConf; import org.apache.hadoop.mapred.Partitioner; public class EdgePartitioner implements Partitioner<Edge, Writable>{ @Override public void configure(JobConf job) { // TODO Auto-generated method stub } @Override public int getPartition(Edge key, Writable value, int numPartitions) { // TODO Auto-generated method stub return key.getDepartureNode().hashCode() % numPartitions; } }
在map和reduce两个阶段之间,一个MapReduce程序必须把mapper的输出分配到多个reducer上,这个过程叫做shuffling,因为一个mapper的输出结果有可能被分配到集群中的多个节点中去。
Combiner----local reduce
在有些情况下,我们希望在分配mapper的结果之前进行一次“local reduce”。比如WordCount程序,我们在处理完一个文档之后得到了“the”1000次,it much more efficient to store and shuffle the pair("the",574) once instread of the pair("the",1) multiple times.这个过程就叫做combiner。今天先简单介绍一下combiner,以后会自己详解。