【问题标题】:Hadoop read multiple lines at a timeHadoop一次读取多行
【发布时间】:2011-11-15 17:21:22
【问题描述】:

我有一个文件,其中每四行一组代表一条记录。

例如,前四行代表记录 1,接下来的四行代表记录 2,依此类推。

如何确保 Mapper 一次输入这四行?

另外,我希望 Hadoop 中的文件拆分发生在记录边界(行号应该是四的倍数),因此记录不会跨越多个拆分文件..

如何做到这一点?

【问题讨论】:

    标签: hadoop


    【解决方案1】:

    一些方法,有些比其他方法更脏:


    正确的方式

    您可能必须定义自己的RecordReaderInputSplitInputFormat。根据您正在尝试做的事情,您将能够重用上述三个中的一些已经存在的。您可能必须编写自己的 RecordReader 来定义键/值对,并且您可能必须编写自己的 InputSplit 来帮助定义边界。


    另一种正确的方式,可能是不可能的

    上述任务相当艰巨。你对你的数据集有任何控制权吗?你能以某种方式对它进行预处理(无论是在它进入时还是在静止时)?如果是这样,您应该强烈考虑尝试将您的数据集转换为更易于在 Hadoop 中开箱即用地读取的内容。

    类似:

    ALine1
    ALine2            ALine1;Aline2;Aline3;Aline4
    ALine3
    ALine4        ->
    BLine1
    BLine2            BLine1;Bline2;Bline3;Bline4;
    BLine3
    BLine4
    

    又脏又臭

    您可以控制数据的文件大小吗?如果您在块边界上手动拆分数据,您可以强制 Hadoop 不关心跨越拆分的记录。例如,如果您的块大小为 64MB,则以 60MB 块的形式写入文件。

    不用担心输入拆分,您可以做一些肮脏的事情:在您的地图函数中,将您的新键/值对添加到列表对象中。如果列表对象中有 4 个项目,则进行处理,发出一些东西,然后清除列表。否则,什么都不发射,什么都不做,继续前进。

    您必须手动拆分数据的原因是您无法保证将整个 4 行记录提供给同一个地图任务。

    【讨论】:

    • 感谢您的回复,我正在考虑您建议的第二种方法,但那不是也充满了同样的问题吗?如何一次读取四行以将它们附加在一起并创建一行?
    • 你可以用 Perl 或 Python 写一些东西来解决这个问题。这就是我的想法。
    • 使用SequenceFile进行压缩以获得更好的性能,如果文件的预处理完成。
    【解决方案2】:

    另一种方法(简单但在某些情况下可能效率不高)是实现FileInputFormat#isSplitable()。然后输入文件不会被拆分,并且每个地图处理一个。

    import org.apache.hadoop.fs.*;
    import org.apache.hadoop.mapred.TextInputFormat;
    public class NonSplittableTextInputFormat extends TextInputFormat {
        @Override
        protected boolean isSplitable(FileSystem fs, Path file) {
            return false;
        }
    }
    

    正如橙章鱼所说

    In your map function, add your new key/value pair into a list object. If the list object has 4 items in it, do processing, emit something, then clean out the list. Otherwise, don't emit anything and move on without doing anything.

    这有一些开销,原因如下

    • 处理最大文件的时间拖累了作业的完成时间。
    • 数据节点之间可能会传输大量数据。
    • 集群未正确利用,因为地图数 = 文件数。

    ** 以上代码来自Hadoop : The Definitive Guide

    【讨论】:

    • 这个想法听起来很有希望。如何使用 NLinesInputFormat 指定每个映射器的行数。这样它就不会依赖于最大的文件。问题是,我使用的 Hadoop 0.20 没有实现这个功能。有什么想法吗?
    • 在 0.20 中 NLineInputFormat 未在新 API 中实现。您可以尝试将新的 API NLinesInputFormat 从其他版本移植到 0.20。这应该不难,而且您还将学习如何编译和构建 Hadoop jar。
    • 这是设置分割数为1的方法吗?
    猜你喜欢
    • 1970-01-01
    • 2013-10-18
    • 1970-01-01
    • 1970-01-01
    • 2012-07-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-15
    相关资源
    最近更新 更多