2013-06-18 2 views
2

작은 테이블과 큰 비뚤어진 테이블간에 간단한 돼지 조인을합니다. 우리가 mapred.job.shuffle.input.buffer.percent=0.30로 변경하는 경우mapred.job.shuffle.input.buffer.percent = 0.70 일 때 pig join은 감속기에서 OutOfMemoryError를 얻습니다.

org.apache.hadoop.mapred.Task: attempt_201305151351_21567_r_000236_0 : 
Map output copy failure : java.lang.OutOfMemoryError: GC overhead limit exceeded 

가 잘 완료 : 우리 때문에 또 다른 버그 (pig skewed join with a big table causes "Split metadata size exceeded 10000000") :(우리가 기본 mapred.job.shuffle.input.buffer.percent=0.70 우리 이경 일부는 셔플 단계에서 실패를 사용하는 경우

"using skewed"을 사용할 수 없습니다

SpillableMemoryManager: first memory handler call- 
Usage threshold init = 715849728(699072K) used = 504241680(492423K) committed = 715849728(699072K) max = 715849728(699072K) 

는 이유는 무엇입니까 :이 같은 로그 2시간에 있지만 (우리가 사용하는 1000 감속기 중 3 보온재 감속기가있다), 우리는 지체 감속기에서 볼 수 이 일이 일어날까요? 셔플 입력 버퍼가 70 %에있을 때 SplilableMemoryManager가 어떻게 우리를 보호하지 못하게합니까?

답변

2

일반적으로 mapred.job.shuffle.input.buffer.percent = 0.70은 OutOfMemory 오류를 발생시키지 않습니다.이 구성은 축소 기의 힙 중 최대 70 %가 섞인 데이터를 저장하는 데 사용되기 때문입니다. 그러나, 내 연습에 OutOfMemory 오류가 발생할 수있는 두 가지 시나리오가 있습니다.

1) 프로그램에 combine() 함수가 있고 combine()가 메모리를 많이 차지합니다. 따라서 메모리 사용량이 shuffle 단계에서 힙의 70 %를 초과하여 OutOfMemory 오류가 발생할 수 있습니다. 그러나 일반적으로 Pig는 Join 연산자에 combine()를 가지고 있지 않습니다.

2) JVM은 메모리 자체를 관리하고 그 힙을 Eden, S0, S1 및 이전 공간으로 나눕니다. S0와 S1은 GC에 사용됩니다. 경우에 따라 S0 + S1 + 부분 셔플 된 데이터 (70 % 힙)> 힙 크기. 따라서 OutOfMemory가 발생합니다.

위에서 언급 한 것처럼 mapred.job.shuffle.input.buffer.percent = 0.30 일 때 셔플 링 된 데이터를 저장하는 데 30 %의 힙만 사용되므로 힙을 가득 채울 수 없습니다. 좀 더 구체적인 답변을 제공하기 위해 작업의 세부 구성 (예 : Xmx), 데이터 크기 및 로그가 필요합니다.

SpillableMemoryManager라고 말하면 Pig의 기본 콜렉션 데이터 구조는 "백"입니다. 가방은 엎질러 진 것입니다. 즉 RAM에있는 가방에 모든 튜플을 보관할 수있는 메모리가 충분하지 않으면 돼지가 가방의 일부를 디스크에 쏟아 붓습니다. 이렇게하면 큰 작업이 "메모리 부족"오류로 인해 충돌하는 대신 천천히 진행하지만 진행할 수 있습니다. (이 단락은 pig's blog입니다.)

그러나 셔플 단계는 Hadoop 자체에서 제어되므로 SpillableMemoryManager는 셔플 단계에서 적용되지 않습니다. 정확히 말하면 그룹화 기준에서 사용되는 combine()에서 적용될 수 있습니다. 그러나 Join에는 combine())가 없습니다. SpillableMemoryManager는 일반적으로 map(), combine(), reduce() 함수에 사용됩니다. 이것이 왜 셔플 입력 버퍼가 70 %에있을 때 SplilableMemoryManager가 실패로부터 우리를 보호하지 않는 이유입니다. Hadoop은 모든 셔플 된 데이터를 메모리에 보유하지 않으며 너무 큰 경우 부분적으로 셔플 된 데이터를 디스크에 병합합니다.

+0

매우 자세히 설명해 주셔서 감사합니다. 그래서 기본적으로 SpillableMemoryManager는 돼지 기능이므로 내 문제와 아무런 관련이 없습니다. 내 문제는 자체 RAM 관리자를 사용하고있는 그 아래의 hadoop 수준에 있습니다. S0와 S1에서 너무 많은 메모리를 차지하는 것이 무엇인지 짐작할 수 있습니까? 셔플 스테이지가 RAM 관리자를 사용한다면, 이것은 메모리의 유일한 큰 요소가 될 것이며, 큰 객체는 다른 메모리를 차지하지 않을 것이라고 기대합니다. – ihadanny

+0

예, SpillableMemoryManager는 문제와 아무 관련이 없습니다. S0, S1, Eden 및 Old Space 사이의 관계를 명확하게 설명하기는 다소 어렵습니다. GC가 발생하면 Eden의 일부 살아있는 객체가 S0/S1 또는 Old로 복사됩니다. 따라서 S0/S1/Old는 이러한 객체를 보관할 여유 공간이 필요합니다. 그래서 JVM은 생각보다 많은 메모리가 필요합니다.최종 질문에 대한 대답은 일반적으로 예입니다. 그러나 ReduceTask.java에서 일부 코드를 변경하면이 가정이 깨질 수 있습니다. –

+0

위의 답변을 업데이트했습니다. combine()가 메모리를 소비하는 경우 추가 큰 객체가 셔플 페이즈에 존재할 수 있습니다. –