在hadoop map reduce中使用分组比较器有什么用

时间:2013-02-06 11:54:54

标签: hadoop mapreduce hadoop-partitioning

我想知道为什么在第二种mapreduce中使用分组比较器。

根据二级排序的权威指南示例

我们希望键的排序顺序为年(升序),然后是 温度(下降):

1900 35°C
1900 34°C
1900 34°C
...
1901 36°C
1901 35°C

通过按键的年份部分设置分区来分区,我们可以保证 同年的记录转到相同的减速机。这仍然不足以实现我们的目标 然而,目标。分区程序仅确保一个reducer接收所有记录 一年;它不会改变reducer在分区内按键分组的事实。

因为我们已经编写了我们自己的分区器来处理特定reducer的map输出键,所以我们为什么要对它进行分组。

提前致谢

4 个答案:

答案 0 :(得分:35)

为了支持我选择的答案,我补充说:

继续this explanation

**Input**:

    symbol time price
    a      1    10
    a      2    20
    b      3    30

**Map output**: create composite key\values like so:

> symbol-time time-price
>
>**a-1**         1-10
>
>**a-2**         2-20
>
>**b-3**         3-30

分区程序:将a-1和a-2键路由到同一个reducer,尽管键不同。它还将b-3路由到一个单独的减速器。

GroupComparator :一旦复合键\值到达reducer而不是reducer得到

>(**a-1**,{1-10})
>
>(**a-2**,{2-20})

由于合成后的唯一键值,上述情况会发生。

组比较器将确保减速器得到:

(a-1,{**1-10,2-20**})

分组值的关键字将是组中第一个出现的值。这可以通过密钥比较器来控制。

**[[In a single reduce method call.]]**

答案 1 :(得分:23)

让我改进声明“......照顾到特定减速器的地图输出键”。

Reducer Instance vs reduce方法: 每个Reduce任务创建一个JVM,每个JVM都有一个Reducer类实例。这是Reducer实例(我从现在开始称之为Reducer)。在每个Reducer中,根据'key grouping'调用reduce方法多次。每次调用reduce时,'valuein'都有一个地图输出值列表,按照你在'分组比较器'中定义的键分组。默认情况下,分组比较器使用整个地图输出键。

在示例中,地图输出键被更改为“年份和温度”以实现排序。除非您定义仅使用地图输出键的“年”部分的分组比较器,否则您无法进行所有记录同年去同一个reduce方法调用。

答案 2 :(得分:2)

您需要引入一个中间密钥,它是年份和温度的组合;对自然键(年份)进行分区,并引入一个比较器,对整个复合键进行排序。你是对的,通过分割年份,你可以在同一个减速器中获得一年的所有数据,因此比较器将根据温度有效地对每年的数据进行排序。

答案 3 :(得分:1)

默认分区程序计算密钥的哈希值,具有相同哈希值的密钥将发送到同一个reducer。如果您在映射器中发出了复合(自然+扩充)键,并且如果要将具有相同自然键的键发送到同一个reducer,则必须实现自定义分区器。

public class SimplePartitioner implements Partitioner {
@Override
public int getPartition(Text compositeKey, LongWritable value, int numReduceTasks) {
    //Split the key into natural and augment
    String naturalKey = compositeKey.toString().split("separator")


    return naturalKey.hashCode();
}

}

现在,如果您希望数据分区中的所有相关行都发送到单个reducer ,您还必须实现仅考虑自然键的分组比较器

public class SimpleGroupingComparator extends WritableComparator {

@Override
public int compare(Text compositeKey1, Text compositeKey2) {


return compare(compositeKey1.getNaturalKey(),compositeKey2.getNaturalKey());
}

}