【问题标题】:Hadoop: How to output different format types in the same job?Hadoop:如何在同一个作业中输出不同的格式类型?
【发布时间】:2012-10-18 10:55:23
【问题描述】:

我想在一个作业中同时输出gziplzo 格式。

我使用了MultipleOutputs,并添加了两个这样的命名输出:

MultipleOutputs.addNamedOutput(job, "LzoOutput", GBKTextOutputFormat.class, Text.class, Text.class);

GBKTextOutputFormat.setOutputCompressorClass(job, LzoCodec.class);

MultipleOutputs.addNamedOutput(job, "GzOutput", TextOutputFormat.class, Text.class, Text.class);

TextOutputFormat.setOutputCompressorClass(job, GzipCodec.class);

(GBKTextOutputFormat这里是我自己写的,扩展FileOutputFormat)

它们用于减速器,例如:

multipleOutputs.write("LzoOutput", NullWritable.get(), value, "/user/hadoop/lzo/"+key.toString());

multipleOutputs.write("GzOutput", NullWritable.get(), value, "/user/hadoop/gzip/"+key.toString());

结果是:

我可以在两个路径中获得输出,但它们都是gzip 格式。

有人可以帮助我吗?谢谢!

================================================ =============================

更多:

刚刚在FileOutputFormat中查看了setOutputCompressorClass的源码,其中conf.setClass("mapred.output.compression.codec", codecClass, CompressionCodec.class);

似乎在调用 setOutputCompressorClass 时,配置中的 mapred.output.compression.codec 会被重置。

所以实际的压缩格式是我们最后设置的,不能在同一个job中设置两种不同的压缩格式?或者还有什么被忽略的?

【问题讨论】:

  • 您是否确认您的 GBKTextOutputFormat 在用作未运行 MultipleOutput 的 reducer 中的唯一输出格式类型时有效?另外,在您的自定义输出格式类中,压缩类在 getRecordWriter() 方法中设置为 GzipCodec 以外的其他内容?
  • 我的意思是默认压缩类...

标签: hadoop mapreduce gzip lzo


【解决方案1】:

所以也许作为一种解决方法,尝试直接在配置中设置正确的 outputCompressorClass

context.getConfiguration().setOutputCompressorClass(GzipCodec.class);

就在您对每个输出的写入调用之前。看起来,除了键类、值类和输出路径之外的任何输出格式配置参数都没有被 MultipleOutputs 很好地处理,我们可能需要编写一些代码来抵消这种疏忽。

【讨论】:

  • 感谢您的回复!当只有一种输出格式类型时,GBKTextOutputFormat 实际上效果很好。我会尝试在每个multipleOutputs.write(...) 之前设置OutputCompressorClass。
  • 我期待听到它的进展。您实例化的 MultipleOutputs 对象实际上为每个输出缓存了一个 RecordWriter,并且该 RecordWriter 是在您第一次尝试向输出写入内容时构造的。我们讨论过的问题是不同的输出会影响彼此的配置设置,然后无法正确创建 RecordWriters。理论上:)
  • RecordWriter 完全按照您的观点缓存在 MultipleOutputs 对象中。 RecordWriter的上下文通过taskContext = getContext(...);获取,不等于null则直接返回taskContext。这使得我们在 MultipleOutputs.write 之前的 setOutputCompressorClass 不起作用。所以我将 MultipleOutputs 复制为另一个类并修改 getContext() 函数。如果 taskContext != null 则不会返回。现在看起来一切正常,接下来我应该做的是确保 taskContext 只为每个 nameOutput 实例化一次,否则它会运行得太慢。非常感谢!!!
  • 我没有想过要创建一个新的 MultipleOutputs 类。很酷。
  • @thomaslee:看我对这个问题的回答:stackoverflow.com/questions/12981233/…
猜你喜欢
  • 1970-01-01
  • 2012-11-14
  • 2014-07-26
  • 2023-03-08
  • 1970-01-01
  • 1970-01-01
  • 2012-10-13
  • 2012-05-31
  • 2017-07-26
相关资源
最近更新 更多