Hadoop MapReduce 小文件内存不足

Hadoop MapReduce Out of Memory on Small Files

我正在 运行针对 Hadoop 上大约 300 万个小文件执行 MapReduce 作业(我知道,我知道,但我们对此无能为力 - 这是我们源系统的性质)。

我们的代码没有什么特别的——它使用CombineFileInputFormat将一堆这些文件包装在一起,然后解析文件名以将其添加到文件的内容中,并吐出一些结果。简单易行。

所以,我们在 HDFS 中有大约 300 万个 ~7kb 的文件。如果我们 运行 我们的任务针对这些文件的一小部分(一个文件夹,可能有 10,000 个文件),我们不会遇到任何麻烦。如果我们 运行 它针对完整的文件列表,我们会得到内存不足的错误。

错误出现在 STDOUT:

#
# java.lang.OutOfMemoryError: GC overhead limit exceeded
# -XX:OnOutOfMemoryError="kill -9 %p"
#   Executing /bin/sh -c "kill -9 15690"...

我假设正在发生的事情是这样的——无论 JVM 是什么 运行定义输入拆分的进程都变得完全不堪重负试图处理 300 万个文件,它使用了太多内存,并且 YARN 正在杀死它。我愿意在这个理论上得到纠正。

所以,我需要知道如何做的是增加 YARN 计算输入拆分的容器的内存限制,而不是映射器或缩减器。然后,我需要知道如何使它生效。 (我在谷歌上搜索了相当广泛的内容,但是随着 Hadoop 多年来的所有迭代,很难找到适用于最新版本的解决方案...)

这是 Hadoop 2.6.0,在 AWS Elastic MapReduce 4.2.0 上使用 MapReduce API、YARN 框架。

我会启动一个新的 EMR 集群,并向其投放一个更大的主实例,看看是否是问题所在。

--instance-groups InstanceGroupType=MASTER,InstanceCount=1,InstanceType=m3.4xlarge InstanceGroupType=CORE,InstanceCount=1,InstanceType=m3.xlarge

如果master在配置输入拆分时运行内存不足你可以修改配置 EMR Configuration

您可以使用以下任一方法将 MapReduce 合并到可管理的更大文件中,而不是 运行将 MapReduce 用于 300 万个单独的文件。 1. 从小文件创建 Hadoop 存档 (HAR) 文件。 2. 使用 MapReduce 程序为每 10K-20K 文件创建序列文件。 3. 使用 forqlift 工具从您的个人小文件创建一个序列文件。 4. 使用 Hadoop-Crush 将您的小文件合并成更大的文件。

准备好更大的文件后,您可以运行整个数据集上的 MapReduce。