如果在传递到reduce阶段时需要对给定键的值进行排序(例如移动平均值),或者要模仿sql中的lag/lead分析函数,则需要在mapreduce中实现二次排序。
在谷歌上搜索之后,常见的建议是:
a) emit composite key,其中包括,在Map阶段b)创建一个“composite key comparator”类,该类的目的是进行二次排序,比较要排序的值后再对键进行排序,以便对传递给reducer的iterable进行排序。c) 创建一个“natural key grouping comparator”类,该类用于主排序,只比较要排序的键,以便传递给reducer的iterable包含属于给定键的所有值。d) 创建一个“natural key partitioner类”,我不知道它的用途,这也是我的问题的目的。
从这里开始:
自然密钥分区器使用自然密钥将数据分区到还原器。再次注意,这里,我们只考虑“自然”键。
当然,自然键指的是实际键,而不是复合键+值。
从这里开始:
默认分区将计算整个密钥上的哈希值,从而产生不同的哈希值,并可能将记录发送到不同的还原器。为了确保两个记录都发送到同一个reducer,让我们实现一个customer partitioner。
从这里开始:
在一个真正的hadoop集群中,有许多reducer运行在不同的节点上。如果同一区域和同一天的数据在Mapreduce shuffle之后没有落在同一个reducer中,我们就有麻烦了。确保这一点的方法是负责定义我们自己的分区逻辑。
我介绍的每个源代码加上我看到的所有其他源代码都建议根据以下伪代码编写partioner类:
naturalKey = compositeKey.getNaturalKey()
return naturalKey.hashCode() % NUMBER_OF_REDUCERS
现在,我的印象是hadoop保证对于一个给定的键,与该键对应的所有值都将指向同一个reducer。
创建自定义分区器的原因是否与创建“自然键分组比较器”类的原因相同,以防止mapreduce发送复合键而不是reducer键?
1条答案
按热度按时间trnvg8h31#
这个问题几乎和答案一样好:),你上面提到的一切都是正确的,我想用不同的方式来解释这个概念应该会有所帮助。
我来试试。
假设我们的二次排序是在由姓和名组成的复合键上。
现在让我们看看二级排序机制
分区器和组比较器仅使用自然密钥,分区器使用它将具有相同自然密钥的所有记录传送到单个缩减器。这种划分发生在map阶段,来自不同map任务的数据由reducer接收,在那里它们被分组,然后被发送到reduce方法。这个分组就是组比较器出现的地方,如果我们没有指定一个自定义的组比较器,那么hadoop将使用默认的实现,该实现将考虑整个复合键,这将导致不正确的结果。