我正在调试一个 OutOfMemoryError
我要加入我的hadoop还原程序。Map程序成功完成。它们生成小于128字节的小记录。在我的reducer中,我使用相同的键(大约有15个可能的键)收集记录,并使用 MultipleOutputs
. 每个键的记录分布不均匀。
在减少阶段的中间,我开始 OutOfMemoryErrors
. 我查了很多东西:
减速器不保存数据;一旦它得到一个值,它就把它写到相应的输出中
我尝试了不同的reduce任务数值。在我的例子中,调整这个有点奇怪,因为超过15个键没有帮助,因为只有15个键
示例化 MultipleOutputs
把它关上 reduce()
,认为它保留了输出文件的资源。这只是因为键和输出文件具有一对一的Map。
我尝试将数据添加到键的末尾,以便数据在reduce任务之间均匀分布
出于偏执, mapreduce.reduce.shuffle.memory.limit.percent=0
验证的键和值确实很小
禁用输出压缩,认为压缩机内存泄漏
盲目地调整 mapreduce.reduce.shuffle.merge.percent
我不知道内存还能往哪里去,除了积极缓冲洗牌输出。
这是在gcpdataproc和hadoop3.2.2上运行的。很多导游都推荐这种设置 mapreduce.reduce.java.opts
. 我尝试了这个方法,但没有成功,但我也假设google为主机大小选择了一个合理的默认值,而且我对内存的去向没有一个令人信服的说法。我的另一个理论是 GoogleHadoopOutputStream
写入云存储的是缓冲。我有一些10gb到100gb之间的输出文件——比机器的内存还大。
我还应该看什么?这些是我应该尝试调整的其他标志吗?连接visualvm看起来并不容易,但是堆转储会有帮助吗?
1条答案
按热度按时间rqdpfwrv1#
每个
GoogleHadoopOutputStream
消耗大约70个mib的jvm堆,因为默认情况下,它将数据以64个mib块的形式上传到google云存储。这就是为什么如果在同一mr任务中使用MultipleOutputs
,每个任务将需要number of outputs x 70 MiB
jvm堆。您可以减少每个应用程序所消耗的内存
GoogleHadoopOutputStream
通过fs.gs.outputstream.upload.chunk.size
但这也会降低到google云存储的上传速度,这就是为什么更好的方法是重新考虑mr作业的因素,以便在每个mr任务中编写单个/更少的文件。