我们在一张小桌子和一张大歪斜的桌子之间做一个简单的猪连接。
由于另一个错误(pig skewed join with a big table causes "Split metadata size exceeded 10000000"),我们无法使用"using skewed"
:(
如果我们使用默认的mapred.job.shuffle.input.buffer.percent=0.70
,我们的一些Reducer会在shuffle阶段失败:
org.apache.hadoop.mapred.Task: attempt_201305151351_21567_r_000236_0 :
Map output copy failure : java.lang.OutOfMemoryError: GC overhead limit exceeded
如果我们将它更改为mapred.job.shuffle.input.buffer.percent=0.30
它会很好地完成,虽然在2小时内(我们使用的1000个减速器中有3个滞后减速器),我们可以在滞后减速器中看到这样的事情:< / p>
SpillableMemoryManager: first memory handler call-
Usage threshold init = 715849728(699072K) used = 504241680(492423K) committed = 715849728(699072K) max = 715849728(699072K)
为什么会这样?当shuffle输入缓冲区达到70%时,SplilableMemoryManager如何保护我们不会失败?
答案 0 :(得分:2)
一般来说,mapred.job.shuffle.input.buffer.percent = 0.70不会触发OutOfMemory错误,因为此配置可确保最多70%的reducer堆用于存储混洗数据。但是,有两种情况可能导致我的练习中出现OutOfMemory错误。
1)你的程序有combine()函数,你的combine()很耗费内存。因此,在shuffle阶段内存使用量可能会超过堆的70%,这可能会导致OutOfMemory错误。但一般来说,Pig在Join运算符中没有combine()。
2)JVM管理内存本身并将其堆分为Eden,S0,S1和旧空间。 S0和S1用于GC。在某些情况下,S0 + S1 +部分洗牌数据(70%堆)&gt;堆大小。所以OutOfMemory发生了。
正如您所提到的,当mapred.job.shuffle.input.buffer.percent = 0.30时,只有30%的堆用于存储随机数据,堆很难满。我需要作业的详细配置(例如Xmx),数据大小和日志来为您提供更具体的答案。
说到SpillableMemoryManager。 Pig中的默认集合数据结构是“Bag”。包是可以溢出的,这意味着如果没有足够的内存来将所有元组保存在RAM中的包中,Pig会将部分包装溢出到磁盘上。这允许大型工作虽然进展缓慢,但不会因“内存不足”错误而崩溃。 (此段落来自pig's blog)
然而,shuffle阶段由Hadoop本身控制,因此SpillableMemoryManager在shuffle阶段不起作用(确切地说,它可以在Group By中使用的combine()中生效。但是Join没有combine() )。 SpillableMemoryManager通常用于map(),combine(),reduce()函数。这就是当shuffle输入缓冲区达到70%时,SplilableMemoryManager不能保护我们免于失败的原因。请注意,Hadoop不会将所有洗牌数据保存在内存中,如果它们太大,它会将部分洗牌数据合并到磁盘上。