0

我有一个流式 map-reduce 工作。我有大约 30 个插槽用于处理。最初我得到一个包含 60 条记录的输入文件(字段以制表符分隔),每条记录的第一个字段是一个数字,第一个记录号(第一个字段)是 1,第二个记录号(第一个字段)是 2,依此类推. 我想从这些记录中创建 30 个文件以进行下一步处理,每个文件都包含 2 条记录(均匀分布)。

为此,我将 hadoop 作业的 reducer 数量指定为 30。我预计第一个字段将用作键,我将获得 30 个输出文件,每个输出文件包含 2 条记录。

我确实得到了 30 个输出文件,但并非所有文件都包含相同数量的记录。有些文件甚至是空的(零大小)。任何想法

4

2 回答 2

0

默认情况下,Hadoop suffle 并将 Map 任务输出组合为 Reducer 输入。因此具有相同键值的 Map 输出集映射到相同的 reducer。因此通过这样做,一些 reducer 可能没有输入集,所以说 part-00005 文件的大小0 KB。

于 2012-05-29T06:56:40.313 回答
0

你的输出键类型是什么?如果您使用的是 Text 而不是 IntWritable (我假设您必须像使用流式传输一样),则减少数是根据字节表示的哈希值计算的,即键值的 UTF-8“字符串”。您可以编写一个简单的单元测试来观察这一点:

public class TextHashTest {
    @Test
    public void testHash() {
        int partitions = 30;
        for (int x = 0; x < 100; x++) {
            int hash = new Text(String.valueOf(x)).hashCode();
            int part = hash % partitions;
            System.err.printf("%d = %d => %d\n", x, hash, part);            
        }
    }
}

我不会粘贴输出,但在 100 个值中,分区箱 0-7 永远不会收到任何值。

因此,就像Thomas Jungblut在他的评论中所说,您需要编写一个自定义分区器将 Text 值转换回整数值,然后将该数字与分区总数取模 - 但这可能仍然不会给您“偶数”如果值本身不在 1-up 序列中,则分布(你说它们是这样的,所以你应该没问题)

public class IntTextPartitioner implements Partitioner<Text, Text> {
    public void configure(JobConf job) {}

    public int getPartition(Text key, Text value, int numPartitions) {
        return Integer.valueOf(key.toString()) % numPartitions;
    }            
}
于 2012-05-30T01:45:03.003 回答