所以我有一些Pig脚本在作业的reduce阶段不断死亡,错误是Java堆不断耗尽空间。到目前为止,我唯一的解决方案是增加Reducer计数,但这似乎并没有让我在任何可靠的地方。现在,部分原因可能只是我们正在获得的数据的大量增长,但不能确定。
我想过改变溢出阈值设置,不能回忆设置,但不确定他们是否会帮助任何或只是减慢它。我还能做些什么来解决这个问题?
附带说明一下,当这种情况开始发生时,我也会得到bash无法获得内存的错误,我认为这是泄漏操作。这是Hadoop节点内存不足吗?如果是这样的话,仅仅降低这些盒子上的堆大小是解决方案吗?
编辑1
1)猪0.8.1
2)唯一的UDF是一个eval UDF,它只查看单行,没有包或映射。
3)我没有注意到有密钥分发不好的热点。我也一直在使用质数尺度来减少这个问题。
编辑2
下面是有问题的错误:
2012-01-04 09:58:11,179 FATAL org.apache.hadoop.mapred.TaskRunner: attempt_201112070707_75699_r_000054_1 : Map output copy failure : java.lang.OutOfMemoryError: Java heap space
at org.apache.hadoop.mapred.ReduceTask$ReduceCopier$MapOutputCopier.shuffleInMemory(ReduceTask.java:1508)
at org.apache.hadoop.mapred.ReduceTask$ReduceCopier$MapOutputCopier.getMapOutput(ReduceTask.java:1408)
at org.apache.hadoop.mapred.ReduceTask$ReduceCopier$MapOutputCopier.copyOutput(ReduceTask.java:1261)
at org.apache.hadoop.mapred.ReduceTask$ReduceCopier$MapOutputCopier.run(ReduceTask.java:1195)
这是我一直得到的bash错误:
java.io.IOException: Task: attempt_201112070707_75699_r_000054_0 - The reduce copier failed
at org.apache.hadoop.mapred.ReduceTask.run(ReduceTask.java:380)
at org.apache.hadoop.mapred.Child.main(Child.java:170)
Caused by: java.io.IOException: Cannot run program "bash": java.io.IOException: error=12, Cannot allocate memory
at java.lang.ProcessBuilder.start(ProcessBuilder.java:460)
at org.apache.hadoop.util.Shell.runCommand(Shell.java:149)
at org.apache.hadoop.util.Shell.run(Shell.java:134)
at org.apache.hadoop.fs.DF.getAvailable(DF.java:73)
at org.apache.hadoop.fs.LocalDirAllocator$AllocatorPerContext.getLocalPathForWrite(LocalDirAllocator.java:329)
at org.apache.hadoop.fs.LocalDirAllocator.getLocalPathForWrite(LocalDirAllocator.java:124)
at org.apache.hadoop.mapred.MapOutputFile.getInputFileForWrite(MapOutputFile.java:160)
at org.apache.hadoop.mapred.ReduceTask$ReduceCopier$InMemFSMergeThread.doInMemMerge(ReduceTask.java:2537)
at org.apache.hadoop.mapred.ReduceTask$ReduceCopier$InMemFSMergeThread.run(ReduceTask.java:2501)
显然您在某处内存不足。增加减速器的数量实际上是相当合理的。看看JobTracker Web GUI上的统计数据,看看有多少字节从映射器流出。用它除以reduce任务的数量,这就是每个reducer得到的一个相当粗略的估计。不幸的是,这只有在您的密钥均匀分布的情况下才能长期有效。
在某些情况下,JOIN
(特别是复制类型)会导致这种类型的问题。当您有一个特定键的"热点"时,就会发生这种情况。例如,假设您正在执行某种连接,其中一个键在50%的时间内出现。不管哪个减速机幸运地处理了这个键,都会被打败。您可能需要调查哪些键会导致热点,并相应地处理它们。根据我的数据,通常这些热点都是无用的。要找出什么是热的,只要做一个GROUP BY
和COUNT
,找出什么是经常出现的。然后,如果它没有用,就用FILTER
把它去掉。
这个问题的另一个来源是Java UDF聚合了太多的数据。例如,如果您有一个UDF,它遍历一个数据包并将记录收集到某种列表数据结构中,那么您可能会使用热点值来消耗内存。
我发现新版本的Pig ()特别是。8和。9)内存问题要少得多。我在。7中遇到过不少堆不足的情况。这些版本有更好的溢出到磁盘检测,所以如果它要吹堆,它足够聪明地溢出到磁盘。
为了让我更有帮助,你可以发布你的Pig脚本,并说明你使用的是哪个版本的Pig。
我不是一个有经验的用户,但我在VM上运行pig作业时确实遇到了类似的问题。
我的特殊问题是,VM没有配置交换空间,它最终会耗尽内存。我猜你正在尝试在一个适当的linux配置,但它不会伤害做一个:free -m
,看看你得到的结果,也许问题是由于你有太少的交换内存配置。
只是一个想法,让我知道它是否有用。祝你好运!