我在用Python进行Hadoop数据处理,应该用什么文件格式?

3 投票
2 回答
1674 浏览
提问于 2025-04-15 18:31

我正在用Hadoop和Python处理数据,应该使用什么文件格式呢?

我有一个项目,里面有很多文本页面。

每个文本文件都有一些我需要保留的头部信息;不过,我不想让这些头部信息影响到聚类算法的运行。

我在Hadoop上使用Python(或者有没有更合适的子包?)

我应该如何格式化我的文本文件,并把这些文本文件存储在Hadoop中进行处理呢?

2 个回答

1

如果你在使用Hadoop Streaming,你的输入可以是任何基于行的格式;你的映射器(mapper)和归约器(reducer)的输入来自系统标准输入(sys.stdin),你可以随意读取。你不一定要使用默认的以制表符分隔的字段(不过根据我的经验,尽量在所有任务中使用统一的格式会更好)。

但是,使用默认的分隔符和分区器,你无法控制输入和输出是如何分区或排序的,所以你的映射器和归约器必须仅凭某一行来判断这行是标题行还是数据行——它们不知道原始文件的边界。

你可以指定一个分区器,让映射器假设第一行输入是文件的第一行,或者甚至可以不使用基于行的格式。上次我尝试使用Streaming时,这个操作比较困难。在我看来,映射器和归约器的任务应该对输入格式不敏感,以提高效率和可重用性——最好把输入看作是一串记录,而不是去关注文件的边界。

使用Streaming的另一个选择是将标题信息放在一个单独的文件中,并与数据一起发送。这样,映射器和归约器在它们的工作目录中就能访问到这些信息。一个想法是,在初始任务中将每一行与相应的标题信息关联,也许可以用每行三个字段而不是两个字段,而不是按文件来关联。

总的来说,尽量把输入当作一个流来处理,不要依赖文件的边界、输入的大小或顺序。这些限制都可以实现,但会增加复杂性。如果你确实需要实现这些,最好在任务链的开始或结束时进行。

如果你使用Jython或SWIG,你可能会有其他选择,但我发现这些比Streaming更难处理。

4

1) 文件

如果你使用Hadoop Streaming,你必须使用基于行的文本文件,数据会在第一个制表符之前作为键传递给你的映射器。

你可以查看这个文档来了解流处理的相关信息。

你也可以把输入文件放到HDFS中,这对于大文件是推荐的做法。可以查看上面链接中的“大型文件”部分。

2) 元数据保存

我看到的问题是,你的头部信息(元数据)只会被当作普通数据处理,所以你需要自己过滤掉(第一步)。要将其传递下去更困难,因为所有输入文件的数据在映射步骤后会被简单地合并在一起。

你需要在数据本身中添加元数据(第二步),以便后续能够关联。你可以为每一行数据发出(键,数据+元数据),这样就能为每一行数据保留元数据。虽然这可能会增加很多开销,但我们在讨论MapReduce,所以这也是可以理解的;)

接下来是我不太确定流处理和Java实现的作业有多大区别的部分。如果流处理每个文件调用一个映射器,你可以省去后面的麻烦,只需将map()的第一个输入作为元数据,并将其(或一个占位符)添加到所有后续的数据输出中。如果不是,接下来是关于Java作业的内容:

至少使用JAR映射器时,你可以将数据与其输入文件关联起来(见这里)。但你需要先提取元数据,因为映射函数可能只在不包含元数据的文件分区上被调用。我建议可以这样做:

  • 提前创建一个元数据文件,包含一个占位符索引:keyx:filex, metadatax
  • 将这个元数据索引放入HDFS中
  • 使用JAR映射器,在setup()中加载元数据索引文件
    • 参见 org.apache.hadoop.hdfs.DFSClient
  • 匹配filex,为这个映射器设置keyx
  • 在map()中为每一行输出的数据添加使用的keyx

撰写回答