Hadoop具有推测执行的多个输出

时间:2015-05-05 19:43:08

标签: java hadoop yarn multipleoutputs speculative-execution

我有一个任务,它将avro输出写入由输入记录的几个字段组织的多个目录中。

For example : 
Process records of countries across years 
and write in a directory structure of country/year 
eg:
outputs/usa/2015/outputs_usa_2015.avro 
outputs/uk/2014/outputs_uk_2014.avro
AvroMultipleOutputs multipleOutputs=new AvroMultipleOutputs(context);
....
....
     multipleOutputs.write("output", avroKey, NullWritable.get(), 
            OUTPUT_DIR + "/" + record.getCountry() + "/" + record.getYear() + "/outputs_" +record.getCountry()+"_"+ record.getYear());

下面的代码用什么输出提交器来编写输出。用于推测执行是不安全的?  通过推测执行,这会导致(可能导致)org.apache.hadoop.hdfs.server.namenode.LeaseExpiredException

在这篇文章中 Hadoop Reducer: How can I output to multiple directories using speculative execution? 建议使用自定义输出提交器

hadoop AvroMultipleOutputs的以下代码未说明推测执行有任何问题

 private synchronized RecordWriter getRecordWriter(TaskAttemptContext taskContext,
          String baseFileName) throws IOException, InterruptedException {

    writer =
                ((OutputFormat) ReflectionUtils.newInstance(taskContext.getOutputFormatClass(),
                    taskContext.getConfiguration())).getRecordWriter(taskContext);
...
}

如果baseoutput路径在作业目录

之外,write方法也不会记录任何问题
public void write(String namedOutput, Object key, Object value, String baseOutputPath)

在作业目录外写作时,AvroMultipleOutputs(其他输出)是否存在推测执行的实际问题? 如果,那么我如何覆盖AvroMultipleOutputs以拥有它自己的输出提交器。我无法在AvroMultipleOutputs中查看其使用的输出提交器的任何输出格式

2 个答案:

答案 0 :(得分:1)

AvroMultipleOutputs将使用您已注册到作业配置的OutputFormat,同时添加命名输出,例如使用来自addNamedOutput的{​​{1}} API(例如AvroMultipleOutputs)。

使用AvroKeyValueOutputFormat,您可能无法使用推测任务执行功能。即使压倒它也无济于事或不简单。

相反,您应该编写自己的AvroMultipleOutputs(最有可能扩展其中一种可用的Avro输出格式,例如OutputFormat),并覆盖/实现其AvroKeyValueOutputFormat API,它将返回一个getRecordWriter实例说RecordWriter(仅供参考)。

MainRecordWriter会维护MainRecordWriter(例如RecordWriter)个实例的地图。这些AvroKeyValueRecordWriter个实例中的每一个都属于一个输出文件。在RecordWriter的{​​{1}} API中,您将从地图中获取实际的write实例(基于您要编写的记录),并使用此记录编写器编写记录。所以MainRecordWriter只是作为多个RecordWriter实例的包装器工作。

对于某些类似的实现,您可能希望从MainRecordWriter库中学习MultiStorage类的代码。

答案 1 :(得分:0)

当您向AvroMultipleOutputs添加命名输出时,它会调用AvroKeyOutputFormat.getRecordWriter()AvroKeyValueOutputFormat.getRecordWriter(),调用AvroOutputFormatBase.getAvroFileOutputStream(),其内容为

protected OutputStream getAvroFileOutputStream(TaskAttemptContext context) throws IOException {
  Path path = new Path(((FileOutputCommitter)getOutputCommitter(context)).getWorkPath(),
    getUniqueFile(context,context.getConfiguration().get("avro.mo.config.namedOutput","part"),org.apache.avro.mapred.AvroOutputFormat.EXT));
  return path.getFileSystem(context.getConfiguration()).create(path);
}

并且AvroOutputFormatBase延伸FileOutputFormat(上述方法中的getOutputCommitter()实际上是对FileOutputFormat.getOutputCommitter()的调用。因此,AvroMultipleOutputs应该具有相同的约束为MultipleOutputs