【问题标题】:Reducer receives identical value multiple times instead of expected inputReducer 多次接收相同的值而不是预期的输入
【发布时间】:2014-11-27 13:56:50
【问题描述】:

在我的本地 hadoop 环境中编写 map-reduce 作业时,我遇到了 Reducer 没有收到我预期的值的问题。我将问题抽象为以下内容:

我创建了一个包含 10 行的任意输入文件,以使 map 方法执行 10 次。在映射器中,我创建了一个调用计数并将此计数作为值写入输出,如果值为偶数,则将 0 作为键,如果值为奇数,则将 1 作为键,即以下 (key, value) 对:

(1,1)、(0,2)、(1,3)、(0,4)、(1,5)等

我希望收到两个对 Reducer 的调用

  • 0 > [2,4,6,8,10]
  • 1 > [1,3,5,7,9]

但我接到两个电话

  • 0 > [2,2,2,2,2]
  • 1 > [1,1,1,1,1]

相反。似乎我收到了在映射器中写入的第一个值,其中包含键的多重性(如果我反转计数器,我收到值 10 和 9 而不是 2 和 1)。据我了解,这不是预期的行为(?),但我无法弄清楚我做错了什么。

我使用以下 Mapper 和 reducer:

public class TestMapper extends Mapper<LongWritable, Text, IntWritable, IntWritable> {
    int count = 0;

    @Override
    protected void map(LongWritable keyUnused, Text valueUnused, Context context) throws IOException, InterruptedException {
        count += 1;
        context.write(new IntWritable(count % 2), new IntWritable(count));

        System.err.println((count % 2) + "|" + count);
    }
}

public class TestReducer extends Reducer<IntWritable, IntWritable, IntWritable, IntWritable>{
    @Override
    protected void reduce(IntWritable key, Iterable<IntWritable> valueItr, Context context) throws IOException, InterruptedException {
        List<IntWritable> values = Lists.newArrayList(valueItr);

        System.err.println(key + "|" + values);
    }
}

我使用本地测试运行程序运行 hadoop 作业,例如“Hadoop:权威指南”(O'Reilly)一书中所述:

public class TestDriver extends Configured implements Tool {
    @Override
    public int run(String[] args) throws Exception {
        if (args.length != 2) {
            System.err.printf("Usage: %s [generic options] <input> <output>\n",
                    getClass().getSimpleName());
            ToolRunner.printGenericCommandUsage(System.err);
            return -1;
        }

        Job jobConf = Job.getInstance(getConf());
        jobConf.setJarByClass(getClass());
        jobConf.setJobName("TestJob");  

        jobConf.setMapperClass(TestMapper.class);
        jobConf.setReducerClass(TestReducer.class);

        FileInputFormat.addInputPath(jobConf, new Path(args[0]));
        FileOutputFormat.setOutputPath(jobConf, new Path(args[1]));

        jobConf.setOutputKeyClass(IntWritable.class);
        jobConf.setOutputValueClass(IntWritable.class);

        return jobConf.waitForCompletion(true) ? 0 : 1;
    }

    public static void main(String[] args) throws Exception {
        System.exit(ToolRunner.run(new TestDriver(), args));
}

打包在 jar 中并使用“hadoop jar test.jar infile.txt /tmp/testout”运行。

【问题讨论】:

    标签: hadoop mapreduce


    【解决方案1】:

    Hadoop 在流式传输 reducer 值时重用值对象。

    所以为了捕捉你所有不同的价值观,你需要复制:

    @Override
    protected void reduce(IntWritable key, Iterable<IntWritable> valueItr, Context context) throws  IOException, InterruptedException {        
        List<IntWritable> values = Lists.newArrayList();
        for(IntWritable writable : valueItr) {
            values.add(new IntWritable(writable.get());
        }
    
        System.err.println(key + "|" + values);
    }
    

    【讨论】:

    • 谢谢!那是我想念的地方:)
    猜你喜欢
    • 2013-11-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-28
    • 2020-07-05
    • 2014-12-11
    • 2020-03-12
    相关资源
    最近更新 更多