如何处理无法丢弃的500 MB+;hadoop中的输入文件?

如何处理无法丢弃的500 MB+;hadoop中的输入文件?,hadoop,mapreduce,Hadoop,Mapreduce,我正在编写一个hadoop MapReduce作业,它运行在完整Debian镜像的所有源代码文件上(≈ 40GB)。由于Debian镜像数据位于单独的机器上,而不在hadoop集群中,因此第一步是下载数据 我的第一个实现下载一个文件并输出key=$debian\u包,value=$file\u内容。然后,每个键的不同值(通常为4)应减少为单个条目。下一个MapReduce作业将在debian包上作为键操作,并将其所有文件作为值操作 然而,我注意到hadoop在输出值有时可能非常大(700MB是我

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

我的第一个实现下载一个文件并输出key=$debian\u包,value=$file\u内容。然后,每个键的不同值(通常为4)应减少为单个条目。下一个MapReduce作业将在debian包上作为键操作,并将其所有文件作为值操作

然而,我注意到hadoop在输出值有时可能非常大(700MB是我见过的最大值)时工作得非常糟糕。在MapReduce框架的各个地方,整个文件都存储在内存中,有时存储两次甚至三次。我经常遇到内存不足错误,即使java堆大小为6GB

现在我想知道如何分割数据,使其更好地匹配hadoop的64MB块大小

我不能简单地将大文件分成多个部分,因为它们是压缩的(tar/bz2、tar/xz、tar/gz,将来可能还有其他文件)。在我向dpkg source提供这些文件以提取整个包(必要!)之前,这些文件需要保持其完整大小

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


有没有其他我一直缺少的技巧?你有什么建议吗?

你说得对。这不是Hadoop内部的好例子。大量复制。。。有两个显而易见的解决方案,假设您不能将其解压到某个地方:

  • 使用允许您递归读取压缩和归档文件的任意库分解tarball(apachevfs在这方面的能力有限,但apache压缩库的能力更强)
  • nfs将一组数据节点本地空间装载到主节点,然后获取并卸载到该目录结构中。。。然后使用forqlift或类似的实用程序将小文件加载到HDFS中

  • 另一种选择是编写一个实用程序来实现这一点。我是为一个客户做的。Apache VFS和compression、truezip,然后是hadoop库来编写(因为我做了一个通用实用程序,所以我使用了很多其他库,但这是基本流程)。

    我非常确定hadoop在输出值时不是很差,而是发出了一个超出内存大小的巨大输出字符串。是什么让你如此确定?我正在输出BytesWritable对象,并将它们缩减为ArrayWritable。多重分配问题的一个实例是(1.5倍放大),另一个实例是(2倍最大值大小分配)。还有很多我没有深入研究。我确信hadoop不是为500 MB以上的输出值而设计/测试的。实现你自己的
    BytesWritable
    ,这不会浪费在调整大小上(为什么你首先要调整大小?)。通常大于64mb缓冲区的记录会立即溢出到磁盘。但不知道为什么要发出500 mb的记录。我没有明确地调整大小,反序列化时会自动调用此方法(即馈送到减速机)。我知道大记录会立即被泄露。我想我解释了500 MB记录的原因:一些源tarball非常大(例如500 MB),我需要将它们从第一个MapReduce(下载)到第二个MapReduce(解包),然后才能拆分它们。