Hadoop一次读取多行

Hadoop一次读取多行,hadoop,Hadoop,我有一个文件,其中每四行代表一条记录 例如,前四行代表记录1,后四行代表记录2,依此类推 如何确保Mapper一次输入这四行 另外,我希望Hadoop中的文件拆分发生在记录边界(行号应该是四的倍数),这样记录就不会跨越多个拆分文件 如何做到这一点?有几种方法,有些比另一些更脏: 正确的方法 您可能需要定义自己的,以及。根据您正试图做的事情,您将能够重用上述三种方法中已有的一些方法。您可能需要编写自己的RecordReader来定义键/值对,并且可能需要编写自己的InputSplit来帮助定义边

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

例如,前四行代表记录1,后四行代表记录2,依此类推

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

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


如何做到这一点?

有几种方法,有些比另一些更脏:


正确的方法

您可能需要定义自己的,以及。根据您正试图做的事情,您将能够重用上述三种方法中已有的一些方法。您可能需要编写自己的RecordReader来定义键/值对,并且可能需要编写自己的InputSplit来帮助定义边界


另一条正确的道路,这可能是不可能的

上述任务相当艰巨。你能控制你的数据集吗?你能以某种方式对它进行预处理吗(在它进入或静止时)?如果是这样,您应该强烈考虑尝试将数据集转换为更容易从Hadoop中读出的东西。

比如:

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

脏兮兮的

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

不用担心输入拆分,您可以做一些肮脏的事情:在map函数中,将新的键/值对添加到列表对象中。如果列表对象中有4个项目,则执行处理、发射某些内容,然后清除列表。否则,不要发射任何东西,不做任何事情就继续前进

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

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

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;
    }
}
正如orangeoctopus所说

在映射函数中,将新的键/值对添加到列表对象中。如果列表对象中有4个项目,则执行处理、发射某些内容,然后清除列表。否则,不要发射任何东西,什么也不做就继续前进。

由于以下原因,这会产生一些开销

  • 处理最大文件的时间拖拽作业完成时间
  • 大量数据可能在数据节点之间传输
  • 由于#of maps=#of file,集群没有得到正确利用

**以上代码来自

谢谢您的回复,我正在考虑您建议的第二种方法,但这不是也有同样的问题吗?如何一次读取四行代码以将它们附加在一起并创建一行代码?您可以用Perl或Python编写一些代码来实现这一点。这就是我的想法。如果对文件进行了预处理,使用压缩可以获得更好的性能。这个想法听起来很有希望。使用NLinesInputFormat指定每个映射器的行数如何。这样它就不会依赖于最大的文件。问题是,我使用的是Hadoop 0.20,它没有实现这一点。。有什么想法吗?在0.20版本中,新API中没有实现NLineInputFormat。您可以尝试将其他版本的新API NLinesInputFormat移植到0.20中。这应该没有那么困难,您还将学习如何编译和构建Hadoop jar。这是将拆分数设置为1的方法吗?