【问题标题】:How can I find out if a task is a reducer or a combiner during run time in Hadoop?如何在 Hadoop 运行时确定任务是减速器还是组合器?
【发布时间】:2012-08-13 04:47:14
【问题描述】:

如果使用 MapReduce 执行的操作不是可交换的和关联的,那么 combiner 不能和 reducer 相同。

例如,在计算平均值时,组合器将键的值求和,然后归约器求和,然后将总和除以该键的值的总数。组合器的代码只有轻微的修改。如果您可以对 combiner 和 reducer 使用相同的类,并且可以确定当前任务是 combiner 还是 reducer,那会怎样?如果它发现它是一个reducer,那么它将总和除以计数。

类似这样的:

protected void reduce(Text keyIn, Iterable<PairWritable> valuesIn,
      Context context)
  throws IOException, InterruptedException {
    double sum = 0.0d;
    long count = 0l;

    for (PairWritable valueIn : valuesIn) {
      sum += valueIn.getSum();
      count += valueIn.getCount();
    }

    if (THIS_IS_A_REDUCER) {
      sum /= count;
    }

    context.write(keyIn, new PairWritable(sum, count));
  }

可以这样做吗?上面的代码THIS_IS_A_REDUCER的和平可以换成什么吗?

我可以从任务尝试 ID 字符串中确定任务是映射器还是减速器,但组合器和减速器似乎具有相似的字符串模式。

【问题讨论】:

  • 定义两个类这么糟糕?你可以从你的组合器中扩展并实现一个额外的抽象方法。例如double finishOperation(double sum, long count) // returns the new sum
  • 扩展合并器是个好主意。你说“定义两个类这么糟糕?”。你是在问还是断言它不好?
  • 问题是您是否对合并器的子类化有信心;)

标签: hadoop mapreduce combiners


【解决方案1】:

这是一个有缺陷的问题。每当您发现需要区分任务调用哪个 reduce() 时。添加组合器。例如,你写

public static class Combine extends MapReduceBase implements Reducer<Text, Text, Text, Text> {
public void reduce(Text key, Iterator<Text> message, OutputCollector<Text, Text> output, Reporter reporter) throws IOException {}

public static class Reduce extends MapReduceBase implements Reducer<Text, Text, Text, Text> {
public void reduce(Text key, Iterator<Text> message, OutputCollector<Text, Text> output, Reporter reporter) throws IOException {}

在main()中,你写

conf.setReducerClass(Reduce.class);
conf.setCombinerClass(Combine.class);

【讨论】:

    【解决方案2】:

    虽然我知道这个问题已经解决了,但我还有另一个解决方案。我所做的就是让我的Combiner 成为Reducer 的子类。然后在 Reducer 代码中,我能够测试我是否是 Combiner 子类。

    这样做的主要好处是我需要在 Reducer 步骤期间修改我的密钥,但不想在 Combining 步骤期间更改它(否则我会应用相同的转换两次)。除此之外,95% 的代码是相同的。

    【讨论】:

    • 或多或少,这就是我为解决问题所做的。我发现任务 ID 解决方案对我来说太复杂了。
    【解决方案3】:

    我想您可以询问Context 对象并获取任务ID。然后,一旦您有了 ID,映射器(包括组合器)的名称中将包含一个“m”,而 reducer 的名称中将包含一个“r”。

    要获取任务尝试 ID,请使用 .getTaskAttemptID()。我认为您应该可以使用 context.getTaskAttemptID() 来使用它,但我无法确定。

    【讨论】:

    • 至少在当前版本中,这并不能回答问题,因为没有专门用于组合器的类型。可用的选项是 , , , ,
    猜你喜欢
    • 2012-12-08
    • 1970-01-01
    • 2016-07-02
    • 2015-06-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-17
    相关资源
    最近更新 更多