如何在Hadoop中运行时确定任务是化简器还是组合器



如果使用MapReduce执行的操作不是交换和关联的,那么组合器不能与化简器相同。

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

像这样:

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 字符串确定任务是映射器还是化简器,但合并器和化简器似乎都有相似的字符串模式。

这是一个有缺陷的问题。每当您发现需要区分任务调用哪个 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);

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

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

我想

你可以询问Context对象并获取任务ID。然后,一旦你有了ID,映射器(包括组合器)的名称中将有一个"m",而化简器的名称中将有一个"r"。

若要获取任务尝试 ID,请使用 .getTaskTryID()。我认为你应该能够做context.getTaskAttemptID()使用它,但我无法确定它。

相关内容

  • 没有找到相关文章

最新更新