Hadoop的可移植键值数据文件格式?

Posted

技术标签:

【中文标题】Hadoop的可移植键值数据文件格式?【英文标题】:Portable Key-Value data file format for Hadoop? 【发布时间】:2012-04-18 21:04:41 【问题描述】:

我正在寻找一种可移植的 Key-Value 数据文件格式,它可以作为 Hadoop 的输入和输出格式,并且除了 Hadoop 之外还可以直接用 C++、Java 和 Python 进行读写。一个问题......我需要支持使用非 Java 映射器和化简器(特别是通过 Hadoop 管道的 c++)进行处理。

有什么想法吗?我应该编写自己的可移植键值文件格式,与 Hadoop 和 Hadoop 管道互操作吗?这种新格式对社区有用吗?

加长版: Hadoop 序列文件(及其近亲 Map、Set、Array 和 BloomMap)似乎是使用 Hadoop 时高效二进制键值数据存储的标准。序列文件的一个缺点是它们只能在 Java 中可读和可写(它们是根据序列化的 Java 对象指定的)。我想构建一个复杂的多阶段 MapReduce 管道,其中各个阶段的输入和输出必须可以从 C++、java 和 python 读取和写入。此外,为了在映射阶段使用大型且高度优化的 c++ 库,我需要能够用 java 以外的语言(即 c++)编写映射器和缩减器。

我考虑过各种解决方法,但没有一个看起来……有吸引力。

    转换 :在每个 MapReduce 阶段之前和之后添加额外的转换阶段,以在序列文件和与其他语言兼容的可移植格式之间转换阶段的输入和输出。 问题:阶段之间消耗和生成的数据非常大 (TB)... 在每个阶段多次复制数据以获取不同编程语言的读/写访问权限是昂贵的。有 10 个阶段,这对我来说开销太大了($$$)。 Avro 文件:使用 Avro 的可移植数据文件格式。 问题:虽然似乎有代码允许可移植 Avro 数据文件用作 MapReduce 中的输入或输出格式,但它仅适用于用 Java 编写的映射器和缩减器。我已经看到了一些关于通过 avro/mapred/tether 包创建对其他语言的映射器支持的讨论,但目前只支持 java。来自文档:“目前只实现了一个 Java 框架,用于测试目的,所以这个功能还没有用。” http://avro.apache.org/docs/1.5.4/api/java/org/apache/avro/mapred/tether/package-summary.html Avro File + SWIG:将 Avro 数据格式与 Java 映射器结合使用,该映射器调用从分布式缓存访问的自定义 SWIG 包装的 c++ 库来进行真正的处理。 Java 字符串的不变性使得编写 SWIG 包装器变得痛苦且效率低下,因为需要一个副本。而且,这么多层次的包装开始成为维护调试和配置的噩梦!

我正在考虑基于与 Hadoop 和 Hadoop Pipes 互操作的 H 文件格式编写我自己的语言可移植键值文件格式...有更好的现成替代方案吗?这种可移植的格式对社区有用吗?

【问题讨论】:

@thomas-jungblut:我也偶然发现了这一点并进行了快速编辑(Avero -> Avro) 【参考方案1】:

我认为你做了几个错误假设:

序列文件的一个缺点是它们只能在 Java 中可读和可写(它们是根据序列化的 java 对象指定的)

取决于您所说的序列化 java 对象的含义。 Hadoop 使用 WritableSerialization 类来提供序列化机制,而不是默认的 Java 序列化机制。您可以将 hadoop 配置为使用默认 Java 序列化 (JavaSerialization),或您选择的任何自定义实现(通过 io.serializations 配置属性)。

因此,如果您使用 Hadoop Writable 机制,您只需要为 C++ 编写一个可以解释序列文件的阅读器,然后编写您希望序列化的类的 c++/python 等价物(但这将是一个痛苦的维护,并引出你的第二个问题,Avro)

此外,为了在映射阶段使用大型且高度优化的 c++ 库,我需要能够用 java 以外的语言(即 c++)编写映射器和化简器

您可以在 python/c++/任何当前使用 Hadoop Streaming 的语言中编写映射器/reducers,并使用序列文件来存储中间格式。所有流式传输需要的是您的映射器/缩减器/组合器期望在标准输入上以key\tvalue 对输入(您可以自定义分隔符而不是制表符),并以类似的格式输出(同样是可自定义的)。

http://hadoop.apache.org/common/docs/current/streaming.html(我相信你已经找到了这个链接,但以防万一)。

如果您想将更复杂的键/值对传递给/从您的流式映射器/reducer 怎么办?在这种情况下,我会说考虑自定义 contrib/流式源代码,特别是 PipeMapper、PipeReducer 和 PipeMapRed 类。例如,您可以将输出/输入修改为 <Type-int/str,Length-int,Value-byte[]> 元组,然后修改您的 python / c++ 代码以进行适当的解释。

通过这些修改,您可以使用 Avro 来管理围绕 hadoop 流框架 (Java) 和您的 c++/python 代码之间的序列化的代码。您甚至可以使用 Avro。

最后 - 您是否查看过 AvroAsTextInputFormatAvroTextOutputFormat 类,它们可能正是您正在寻找的(注意,我从未使用过它们)

【讨论】:

感谢您的回复! 序列化 仅 Java 格式 当我声称序列文件是“仅 Java”格式时,我并不是指键值对的序列化(正如您提到的那样可配置),但是写入磁盘的低级字节格式决定了容器格式本身。格式是根据序列化的 java 原语指定的(例如,java 的可变长度整数的内部表示等)。这使得用其他语言编写解析器变得困难。您知道用于序列文件的读取器/写入器的工作 C++ 实现吗? 我发现有人试图在纯python中实现序列文件格式的解析器。不幸的是,它不能正常工作,因为它不处理一些可变长度整数值的解析:github.com/matteobertozzi/Hadoop/tree/master/python-hadoop 这对于用另一种语言创建非 java 序列文件解析器库来说是一个很好的概念验证(例如c++)...不幸的是,我无法通过解析 java 原始类型来调试问题... 为什么我发现 Hadoop Streaming 缺乏 1. 我正在处理二进制数据而不是文本,因此没有自然分隔符或固定大小的格式可用于拆分键和来自标准输入的值。 2. Hadoop Streaming 仅提供 MapReduce API 的有限部分(无分区,无 java 的组合器) 3. 使用 stdin stderr 进行数据传输与第三方库对这些流的其他使用冲突(例如,将状态信息打印到控制台) 4. 几个基准测试表明,与常规 hadoop 相比,hadoop 流式传输具有较高的开销:epcc.sjtu.edu.cn/dmw/racs2011.pdf

以上是关于Hadoop的可移植键值数据文件格式?的主要内容,如果未能解决你的问题,请参考以下文章

Hadoop之HDFS架构设计

hadoop之HDFS

Hadoop序列文件

使用FileSystem类进行文件读写及查看文件信息

对于 Windows NT/10 上的可移植可执行文件,堆是如何以及在哪里分配的?

反汇编基本算法