Combiners和Partitioner编程

Combiners的作用:
     每一个map可能会产生大量的输出,combiner的作用就是在map端对输出先做一次合并,以减少传输到reducer的数据量,
   1)combiner最基本是实现本地key的聚合,对map输出的key排序,value进行迭代。如下所示:map: (K1, V1) → list(K2, V2) combine: (K2, list(V2)) → list(K2, V2) reduce: (K2, list(V2)) → list(K3, V3)
   2)combiner还具有类似本地的reduce功能.例如hadoop自带的wordcount的例子和找出value的最大值的程序,combiner和reduce完全一致。如下所示:map: (K1, V1) → list(K2, V2) combine: (K2, list(V2)) → list(K3, V3) reduce: (K3, list(V3)) → list(K4, V4) 
  3)如果不用combiner,那么,所有的结果都是reduce完成,效率会相对低下。使用combiner,先完成的map会在本地聚合,提升速度。
   4)对于hadoop自带的wordcount的例子,value就是一个叠加的数字,所以map一结束就可以进行reduce的value叠加,而不必要等到所有的map结束再去进行reduce的value叠加。
 
注意:combiner使用的合适,可以在满足业务的情况下提升job的速度,如果不合适,则将导致输出的结果不正确。
Combiner的输出是Reducer的输入,Combiner绝不能改变最终的计算结果。所以从我的想法来看,Combiner只应该用于那种Reduce的输入key/value与输出key/value类型完全一致,且不影响最终结果的场景。比如累加,最大值等。
 
Combiners分析
假设有两个map。
第一个map的输出为:
(1950,0)
 (1950,20)
 (1950,10)
第二个map输出为:
(1950,25)
 (1950,15)
 (1950,30)
Reduce函数被调用是,输入如下:
(1950,[0,20,10,25,15,30])
因为30是最大的值,所以输出如下:
(1950,30)
如果我们使用 combiner:那么reduce调用的时候传入的数据如下:
(1950,[20,30])--(1950,30)
用表达式表示为:
Max(0,20,10,25,15,30)=max(max(0,20,10),max(25,15,30))=max(20,30)=30
 
使用 Combiners要小心
刚才我们是计算最大值可以使用Combiners能提高效率。
如果我们要是求平均值呢?
Avg(0,20,10,25,15,30) = 15
如果使用Combiner会得到什么样的结果呢?
 
第一个map输出为:
 avg(0,20,10) = 10
第二个map输出为:
Avg(25,15,30) = 23
 
输入到reduce出来的结果为:
 
Avg(10,23) = 17.5
 
17.5和15?
 
所以 :使用combiner一定要注意。
 
Partitioner分析
Partitioner 在mapreduce的位置:
Partition主要作用就是将map的结果发送到相应的reduce。这就对partition有两个要求:
1)均衡负载,尽量的将工作均匀的分配给不同的reduce。
2)效率,分配速度一定要快。

1:Partitioner是partitioner的基类,如果需要定制partitioner也需要继承该类。
 
2:HashPartitioner是mapreduce的默认partitioner。计算方法是
which reducer=(key.hashCode() & Integer.MAX_VALUE) % numReduceTasks,得到当前的目的reducer。
 
3:BinaryPatitioner继承于Partitioner< BinaryComparable ,V>,是Partitioner的偏特化子类。该类提供leftOffset和rightOffset,在计算which reducer时仅对键值K的[rightOffset,leftOffset]这个区间取hash。
Which reducer=(hash & Integer.MAX_VALUE) % numReduceTasks
 
4:KeyFieldBasedPartitioner也是基于hash的个partitioner。和BinaryPatitioner不同,它提供了多个区间用于计算hash。当区间数为0时KeyFieldBasedPartitioner退化成HashPartitioner。
 
5.TotalOrderPartitioner这个类可以实现输出的全排序。不同于以上3个partitioner,这个类并不是基于hash的。在下一节里详细的介绍totalorderpartitioner。
 
自定义的Partitioner
1)为何使用Partitioner,主要是想reduce的结果能够根据key再次分类输出到不同的文件夹中。
2)结果能够直观,同时做到对数据结果的简单的统计分析。
 
需求:
 
1、输入的数据文件内容如下(1条数据内容少,1条数据内容超长,3条数据内容正常):
Kaka   1  28 
hua     0  26 
chao   1 
tao     1   22 
mao   0   29   22
 
2、目的是为了分别输出结果,正确的结果输出到一个文本,太短的数据输出到一个文本,太长的输出到一个文本,共三个文本输出。
 
Patitioner接口:
 
public int getPartition(Text key, Text value, int numPartitions);
 
numPartitions为Reduce的个数。
 
注:在本地作业运行器上运行时,只支持0个或一个Reduce。
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
posted on 2013-04-30 17:26  北京_飞狐  阅读(1271)  评论(0编辑  收藏  举报