Debugging Hadoop reducer OutOfMemoryError



我正试图调试我在Hadoop减少器中获得的OutOfMemoryError。映射器成功完成。它们生成小于128字节的小记录。在我的reducer中,我收集具有相同键的记录(大约有15个可能的键),并使用MultipleOutputs将它们写入单独的输出文件。每个键的记录分布是不统一的。

在还原阶段的中间,我开始得到OutOfMemoryErrors。我检查了很多东西:

  • reducer不保存数据;一旦它得到一个值,它将其写入相应的输出
  • 我尝试了不同的reduce任务数值。在我的情况下,调优这个有点奇怪,因为超过15个是没有用的,因为只有15个键
  • 实例化MultipleOutputs并在reduce()中关闭它,认为它保留了输出文件的资源。这只会起作用,因为密钥和输出文件有一对一的映射。
  • 我尝试将数据添加到键的末尾,以便数据在reduce任务之间均匀分布
  • 出于偏执,mapreduce.reduce.shuffle.memory.limit.percent=0
  • 验证的键和值真的很小
  • 关闭输出压缩,认为压缩器存在内存泄漏
  • 盲目调整mapreduce.reduce.shuffle.merge.percent

我不确定除了积极缓冲shuffle输出之外,内存还可以去哪里。

这是运行在GCP Dataproc与Hadoop 3.2.2。很多指南都推荐设置mapreduce.reduce.java.opts。我尝试了一下,但没有成功,但我也假设Google为主机大小选择了一个合理的默认值,而且我没有一个令人信服的关于内存去向的故事。我的另一个理论是GoogleHadoopOutputStream中写云存储的东西是缓冲的。我有一些输出文件在10GB到100GB之间——比机器的内存还大。

我还应该看什么?还有其他旗子需要我调音吗?附加VisualVM看起来并不容易,但是堆转储会有帮助吗?

每个GoogleHadoopOutputStream消耗约70 MiB的JVM堆,因为它在默认情况下以64 MiB块上传数据到Google Cloud Storage。这就是为什么如果您使用MultipleOutputs在同一个MR任务中编写许多对象,每个任务将需要number of outputs x 70 MiBJVM堆。

你可以通过fs.gs.outputstream.upload.chunk.size属性减少每个GoogleHadoopOutputStream消耗的内存,但这也会降低上传到谷歌云存储的速度,这就是为什么一个更好的方法是重构你的MR任务,在每个MR任务中写一个/更少的文件。

相关内容

  • 没有找到相关文章

最新更新