我有一个任务,它将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中查看其使用的输出提交器的任何输出格式
答案 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
。