MapReduce高级编程之本地聚集与Combinner

来源:互联网 发布:金达莱花网络歌手 编辑:程序博客网 时间:2024/05/19 05:03
本篇主要介绍Combinner,这个MapReduce Shuffle中占有重要地位,他能减少磁盘I/O以及网络Fetch时的数据迁移量,在MapReduce Shuffle中存在着三次排序(Map端两次,reduce端一次),每次排序时便会用上一次Combinner函数,也就是这个可有可无的函数一旦定义会被三次调用~~
     然而Combinner的使用需要注意程序的差错性,而且有些情况是不能使用的
     下面就来详细介绍之:
     首先看看使用Combinner时的两个必备条件: 
  1. 由于其执行由MapReduce执行框架负责,因此算法如要保证正确性,必须保证算法结果与combiner无关(即combiner是否执行,执行后产生什么中间结果对算法的最终结果无影响)
  2. MapReduce中,mapper的输出数据就是reducer的输入数据,因此这两种数据的格式是一致的。conbiner必须服从于这个前提(即combiner的输入数据、输出数据必须为mapper的输出格式,即reducer的输入格式)。

下面以一个求平均数的算法为例

首先考虑一个简单的例子:现在要处理一堆类型为<字符串, 整数>的key-value对,目的是输出每个不同key值对应的平均value值。为了更浅显易懂,我们用一个现实中的应用解释一下:现在要对一个大型web站点的用户访问日志(log)信息进行分析,日志为一(用户id, 时长)对的序列,每一个这样的key-value对记录了一次某用户对该网站的访问,其中用户id为该访问用户的id,时长为该次访问会话(session)持续的时间长度。现在需要根据这个日志信息进算每个用户每次访问该网站的平均会话时长。

下图给出了解决这一问题的基本算法。

图3.4 一个简单的求各key平均value的MapReduce算法

这个算法不包括合并器。mapper是一个简单的等价函数,直接将传入的(t,r)对输出。reducer根据输入的(t, [r1,r2...])计算各个t值对应的平均r值。

算法显然正确可用,但有着如下缺点:需要将所有mapper产生的key-value对通过网络传输给reducer,这是效率很低的做法。但与单词计数不同,不能简单地将reduce操作作为combiner使用。试想一下,我们可以这么做一下试试:combiner计算局部数据集的平均值,并将其作为中间结果输入给reducer,reducer根据这个结果计算最终的平均值。根据这个规则构造的反例足以证明这个做法是错误的:

Mean(1,2,3,4,5)≠Mean(Mean(1,2),Mean(3,4,5))

求平均数算法:错误的combiner应用

那应该如何在这个算法中应用combiner呢?我们进行了尝试,下图给出了一种计算结果虽然正确,但违背MapReduce程序设计原则的解决方法。

                                                            

图3.5 一个计算结果正确,但违背

MapReduce程序设计原则的解决方法

通过将和与计数分开存放,图示算法能够正确计算出每个t值对应的平均r值。这是我们第一次使用自定义的数据类型。在前面的计算中,我们的key和value都是基本类型的数据。通过自定义数据类型,我们可以构造更为复杂的数据,将计算所需的数据组织到一起。

但这个算法是不正确的,因为它违背了combiner的设计原则(mapper输出格式与reducer输入格式一致。combiner的输入数据、输出数据必须为mapper的输出格式,即reducer的输入格式)

再次强调一点,combiner的执行是由MapReduce执行框架控制的。而在上述算法中,combiner不执行和执行时送入reducer的是两种完全不同的数据类型(不执行时为(t,[r1,r2...]),执行时为(t,[(s1,c1),(s2,c2)...])))。而如果combiner被超过1次,第2次送入combiner的将不是(t,[r1,r2...])类型的数据,而是(t,[(s1,c1),(s2,c2)...])). 总之,combiner输入和输出数据类型的不一致,是这个算法的错误所在

求平均数算法:针对combiner的修正

下图给出了一个针对上一个算法中存在问题加以改进的平均数算法。

                                                             

图3.6 针对图3.5所示算法中存在的问题修正后的求平均数算法

           通过改变mapper的输出类型,mapper输出类型、combiner输入/输出类型、reducer输入类型三者达到了一致,因此上图所示算法是一个正确、可用的MapReduce算法。

原创粉丝点击