【问题标题】:How to handle unsplittable 500 MB+ input files in hadoop?如何在 hadoop 中处理不可分割的 500 MB+ 输入文件?
【发布时间】:2014-10-22 07:00:40
【问题描述】:

我正在编写一个 hadoop MapReduce 作业,该作业在完整的 Debian 镜像(≈ 40 GB)的所有源代码文件上运行。由于 Debian 镜像数据在单独的机器上,而不是在 hadoop 集群中,所以第一步是下载数据。

我的第一个实现下载一个文件并输出 key=$debian_package, value=$file_contents。然后应将每个键的各种值(通常为 4)减少为单个条目。下一个 MapReduce 作业将作为键操作 debian 包,并将其所有文件作为值操作。

但是,我注意到 hadoop 在输出值有时可能非常大(700 MB 是我见过的最大的)时效果不佳。在 MapReduce 框架的各个地方,整个文件都存储在内存中,有时是两倍甚至三倍。我经常遇到内存不足错误,即使 Java 堆大小为 6 GB。

现在我想知道如何拆分数据,以便更好地匹配 hadoop 的 64 MB 块大小。

我不能简单地将大文件分成多个部分,因为它们是压缩的(tar/bz2、tar/xz、tar/gz,也许将来还会有其他文件)。在我对它们进行 dpkg-source 以将包作为一个整体提取(必要!)之前,文件需要保持其完整大小。

我想到的一个想法是将文件存储在第一个 MapReduce 中的 hdfs 上,并且只将它们的路径传递给第二个 MapReduce。但是,那我绕过了 hadoop 对数据局部性的支持,或者有没有办法解决这个问题?

还有其他我遗漏的技术吗?你有什么推荐的?

【问题讨论】:

  • 我很确定 Hadoop 在输出值时并不是很差,而是您发出的输出字符串超出了您的内存大小。
  • 是什么让你如此确定?我正在输出 BytesWritable 对象并将它们缩减为 ArrayWritable。多重分配问题的一个实例是hadoop.apache.org/docs/r2.3.0/api/src-html/org/apache/hadoop/io/…(1.5 倍放大),另一个是grepcode.com/file/repository.cloudera.com/content/repositories/…(2 倍最大值大小分配)。还有更多我没有挖掘的东西。我确信 hadoop 不是为/测试了 500 MB+ 的输出值。
  • 实现你自己的BytesWritable 不会浪费在调整大小上(为什么你首先要调整大小?)。通常大于 64mb 缓冲区的记录会立即溢出到磁盘。不知道为什么要发出 500 mb 的记录。
  • 我没有明确地调整大小,这个方法在反序列化时自动调用(即馈送到 Reducer)。我知道大记录会立即泄露。我想我解释了为什么 500 MB 记录:一些源 tarball 非常大(例如 500 MB),我需要将它们从第一个 MapReduce(下载)到第二个 MapReduce(解压缩),然后才能拆分它们。跨度>

标签: hadoop mapreduce


【解决方案1】:

你是对的。对于 Hadoop 内部来说,这不是一个好案例。大量复制......有两个明显的解决方案,假设你不能只是在某个地方解压它:

  1. 使用允许递归读取压缩和存档文件的多个库中的任何一个来分解 tarball(apache VFS 对此功能有限,但 apache 压缩库具有更多功能)。
  2. nfs 将一堆数据节点本地空间挂载到您的主节点,然后提取并解压缩到该目录结构中...然后使用 forqlift 或类似实用程序将小文件加载到 HDFS 中。

另一种选择是编写一个实用程序来执行此操作。我已经为一个客户做了这个。 Apache VFS 和压缩、truezip,然后是要编写的 hadoop 库(因为我做了一个通用实用程序,所以我使用了很多其他库,但这是基本流程)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-08-18
    • 2021-05-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-01
    相关资源
    最近更新 更多