【问题标题】:MultipleTextOutputFormat alternative in new API新 API 中的 MultipleTextOutputFormat 替代方案
【发布时间】:2013-02-26 22:26:41
【问题描述】:

因为它突出 MultipleTextOutputFormat 尚未迁移到新的 API。因此,如果我们需要根据动态写入的键值来选择输出目录和输出文件名,那么新的 mapreduce API 有什么替代方案?

【问题讨论】:

    标签: hadoop mapreduce


    【解决方案1】:

    我使用的是 AWS EMR Hadoop 1.0.3,可以根据 k/v 对指定不同的目录和文件。使用MultipleOutputs 类中的以下任一函数:

    public void write(KEYOUT key, VALUEOUT value, String baseOutputPath)
    

    public <K,V> void write(String namedOutput, K key, V value,
                            String baseOutputPath)
    

    以前的write 方法要求键与映射输出键的类型相同(如果您在映射器中使用它)或与reduce 输出键的类型相同(如果您在减速机)。该值也必须以类似的方式输入。

    后一种write 方法要求键/值类型与使用addNamedOutput 函数设置MultipleObjects 静态属性时指定的类型相匹配:

    public static void addNamedOutput(Job job,
                                  String namedOutput,
                                  Class<? extends OutputFormat> outputFormatClass,
                                  Class<?> keyClass,
                                  Class<?> valueClass)
    

    因此,如果您需要的输出类型与 Context 使用的不同,则必须使用后一种 write 方法。

    获取不同输出目录的技巧是传递一个包含目录分隔符的baseOutputPath,如下所示:

    multipleOutputs.write("output1", key, value, "dir1/part");
    

    在我的例子中,这创建了名为“dir1/part-r-00000”的文件。

    我没有成功使用包含.. 目录的baseOutputPath,因此所有baseOutputPaths 都严格包含在传递给-output 参数的路径中。

    有关如何设置和正确使用 MultipleOutputs 的更多详细信息,请参阅我找到的这段代码(不是我的,但我发现它很有帮助;不使用不同的输出目录)。 https://github.com/rystsov/learning-hadoop/blob/master/src/main/java/com/twitter/rystsov/mr/MultipulOutputExample.java

    【讨论】:

    • 我忘了说我测试了基于键/值数据改变baseOutputPath,它成功输出到不同的文件。
    • 我很高兴你提到了它,不过我最终还是找到了它:)
    • 非常感谢“dir1/part”部分,没想到!
    【解决方案2】:

    类似于:Hadoop Reducer: How can I output to multiple directories using speculative execution?

    基本上,您可以直接从 reducer 写入 HDFS - 您只需要警惕推测执行并唯一地命名您的文件,然后您需要实现自己的 OutputCommitter 来清理中止的尝试(这是如果您有真正动态的输出文件夹,则最困难的部分是 - 您需要逐步浏览每个文件夹并删除与中止/失败任务相关的尝试)。一个简单的解决方案是关闭推测执行

    【讨论】:

    • 这听起来并不简单:P MultipleTextOutputFormat 有什么解决方法吗?或者我们可以使用新的 API 实现类似 MultipleTextOutputFormat 的东西吗?
    • 如多个输出的 javadoc 中所述,我在我的工作和减速器中添加了以下代码,它工作正常。在作业中:MultipleOutputs.addNamedOutput(job, namedoutputstring, outputformatclass, keyclass, valueclass);在减速器中: mos = new MultipleOutputs(context); ... /*在运行时计算 */ baseoutput = "abc/xyz/filename"; mos.write(key, value, baseOutput);
    • 不要忘记 cleanup() 中的 mos.close()。
    【解决方案3】:

    要获得最佳答案,请参阅 Hadoop - 权威指南第 3 版。(从第 253 页开始。)

    摘自 HDG 书 -

    “在旧的 MapReduce API 中,有两个类用于产生多个输出:MultipleOutputFormat 和 MultipleOutputs。简单来说,MultipleOutputs 功能更全,但 MultipleOutputFormat 对输出目录结构和文件命名的控制更多。MultipleOutputs 中的新 API 结合了旧 API 中两个多输出类的最佳特性。”

    它有一个关于如何使用 MultipleOutputs API 控制目录结构、文件命名和输出格式的示例。

    HTH。

    【讨论】:

    • MultipleOutputs 是否允许根据键值对动态决定输出文件夹名称或文件名?我不这么认为,如果有办法请告诉我。
    • 是的,伙计,我找不到它!使用 MultipleOutputs,您只能写入 pre-defined 文件路径的 set。你可以通过在你的run() 中使用MultipleOutputs.addNamedOutput() 来做到这一点。我可能在这里遗漏了一些东西,但不想发表这样的声明,如果它在其他地方很容易找到,你至少可以发布一个链接。
    • 我也怀疑您使用了 MultipleTextOutputFormat 或 MultipleOutputs!阅读这本书,它清楚地指出,就在示例之前:与 MutipleTextOutputFormat 相比,使用 MultipleOutputs 时对输出命名的控制较少
    猜你喜欢
    • 2012-07-07
    • 2011-01-27
    • 1970-01-01
    • 2011-01-03
    • 2021-06-10
    • 1970-01-01
    • 1970-01-01
    • 2021-05-15
    • 1970-01-01
    相关资源
    最近更新 更多