본문 바로가기

Tech/Hadoop

[Hadoop]하둡 완벽가이드 요약 (7)

7장


7장은 맵리듀스 작동 방법을 설명한다.

맵리듀스 과정을 먼저 이해하기위해 7장을 먼저 요약한다.

 

JobSubmitter

  • 리소스 매니저에 맵리듀스 잡 ID로 사용될 새로운 어플리케이션 ID를 요청(위 사진에서 2번)
  • 잡의 출력 명세를 확인. 출력 디렉토리가 지정되지 않거나, 이미 존재한다면 에러 전달.
  • 잡의 입력 스플릿을 계산한다. 계산할 수 없을시 에러 전달.
  • 잡 실행에 필요한 JAR 파일, 환경 설정파일, 계산된 입력 스플릿 등 잡 리소스를 공유 파일시스템에 있는 해당 잡 ID이름의 디렉터리에 복사한다. (위 사진에서 3번)
  • 리소스 매니저의 submitApplication()을 호출하여 잡을 제출(위 사진에서 4번)

리소스 매니저가 submitApplication() 메서드의 호출을 받으면, YARN 스케줄러에 요청을 전달한다.

스케줄러는 컨테이너를 하나 할당하고, 어플리케이션 마스터 프로세스를 실행한다.(위 사진 5번에 해당)

 

어플리케이션 마스터는 잡을 초기화 할때, 잡의 진행상황을 추적하기 위해 다수의 북키핑 객체를 생성한다. 이후, 각 태스크로부터 진행 및 종료 보고서를 받는다.(위 사진 6번에 해당)

 

입력 스플릿 정보를 공유파일 시스템으로 부터 읽어온다.(위 사진 7번에 해당)

 

입력스플릿 별로 맵 태스크 객체를 생성한다. 이때 태스크 ID가 발급된다.

어플리케이션 마스터는 맵리듀스 잡을 구성하는 태스크 실행 방법을 결정한다. 잡의 크기가 작다면, 자신의 JVM에서 실행할 수 있다. 이런 잡을 우버 태스크라 한다.

  • 여기서 작은 잡이란?
  • 10개 미만의 매퍼와 하나의 리듀서, HDFS 블록 하나보다 작은 크기의 입력을 말한다.
  • 우버 태스크는 반드시 mapreduce.job.ubertask.enable=True가 되야한다.

 

어플리케이션 마스터는 리소스 매니저에 잡의 모든 맵과 리듀스 태스크를 위한 컨테이너를 요청한다.(위 사진 8번에 해당)

  • 맵 태스크 요청이 리듀스 태스크 요청보다 우선순위가 높다.
  • 리듀스 태스크는 어디에서 실행되던 상관이 없지만, 맵 테스크는 데이터 지역성에 제약을 받는다.

 

리소스 매니저의 스케줄러가 특정 노드 상의 컨테이너를 위한 리소스를 테스크에 할당하면, 어플리케이션 마스터는 노드 매니저와 통신하며 컨테이너를 시작한다(위 사진 9번에 해당)

 

각 태스크는 YarnChild 메인 클래스를 가진 JAVA 어플리케이션으로 실행된다.

태스크를 실행하기 이전에, 잡 환경설정, JAR 파일, 분산 캐시와 관련된 파일 등 필요한 리소스를 로컬로 가져온다.(위 사진 10번)

 

그후, 맵 리듀스 태스크를 실행한다(위 사진 11번)

 

맵, 리듀스 함수가 종료 및 장애가 발생해도 노드매니저는 멈추지 않는다.

맵리듀스 잡은 수행시간이 오래 걸리는 배치 잡이다. 따라서, 진행상황에 대한 피드백을 잘 구성해야한다. 이때 기준은 태스크 완료 비율이다.

  • 입력 레코드 읽기
  • 출력 레코드 쓰기
  • 상태 명세의 설정(report 또는 TaskAttemptContext setStatus() 메서드를 통해)
  • 카운터 증가(reporter의 incrCounter(), increment() 메서드를 사용)
  • Reporter 또는 TaskAttempContext의 progress() 메서드 호출시

잡이 실행되는 동안 클라이언트는 매초마다 어플리케이션을 폴링하고, 최신의 상태를 받는다.

어플리케이션 마스터가 마지막 태스크가 완료되었다는 것을 받으면 잡의 상태를 성공으로 변경한다.

이 시점에서 Counter와 잡 통계가 콘솔에 출력된다.

Response가 HTTP를 통해 전달하도록 설정이 되어있다면, 어플리케이션 마스터는 이때 수행한다.

 


 

태스크 실패하는 경우.

  • 맵 리듀스 함수에서 런타임 에러 발생 시,
    • JVM은 종료되기 이전에 어플리케이션 매니저에게 오류를 보고한다. 이 에러는 사용자 로그에 기록된다. 어플리케이션 마스터는 해당 태스크의 상태를 실패로 변경 후, 해당 리소스를 다른 태스크에서 사용가능하도록 컨테이너를 풀어준다.
  • JVM이 갑작스럽게 종료되는 경우
    • 노드 매니저는 프로세스가 종료되었음을 어플리케이션 마스터에게 전달한다.
  • 태스크에 행이 걸린경우
    • 어플리케이션 마스터가 일정 주기(default. 10분)안에 상태를 전달받지 못할 경우, 해당 태스크의 상태를 실패로 변경한다. 그후 해당 JVM은 강제종료 된다.
    • 주기는 mapreduce.task.timeout의 속성에서 관리할 수 있다.
    • timeout이 0인경우, 비활성화이다. 해당 설정의 경우 태스크를 실패로 변경하지 않으며, 컨테이너 자원 또한 해제하지 않는다. 따라서, 클러스터의 자원을 낭비한다.
  • 태스크가 4번 실패하게 되면, 재시도 하지 않는다.
    • 횟수 제한은 mapreduce.map.maxattempts 속성으로 관리 가능하다.

어플리케이션 마스터가 실패하는 경우.

  • 어플리케이션 마스터는 주기적으로 리소스 매니저에 하트비트를 보낸다.
  • 어플리케이션 마스터 실패 이벤트 발생 시, 리소스 매니저는 이 실패를 감지하고 새로운 컨테이너에서 실행할 새로운 마스터 인스턴스를 시작한다.
  • 잡 히스토리를 사용하여 모든 태스크 상태를 복구한다. 재실행 필요 x
  • 클라이언트는 진행상태를 확인하기 위해 어플리케이션 마스터를 폴링하고 있는데, 새로운 어플리케이션 마스터가 구동 될 시, 리소스 매니저에게 주소를 요청하고 캐싱해서 가지고 있는다.

노드매니저가 실패하는 경우.

  • 크래시에 의해 실패하거나 굉장히 느리게 수행되면 리소스 매니저에게 하트비트 전송을 중단한다.
  • 리소스매니저는 노드매니저가 10분동안 하트비트를 전송하지 않으면, 스케줄링 노드 풀에서 해당 노드매니저를 제거한다.
  • 어플리케이션 실패횟수가 높으면 노드매니저 자체가 실패하지 않아도 노드매니저는 블랙리스트에 등록된다.

리소스매니저가 실패하는 경우.(CRITICAL), (SPOF)

  • HA를 구성하기 위해, Active-Standby로 리소스매니저를 구성한다.
  • 어플리케이션에 대한 모든 정보는 HDFS에 저장된다.

 


 

셔플 & 정렬

각 맵 태스크는 메모리 공간을 가지고 이곳에 결과를 기록한다.

기본 메모리 크기는 100MB이고, 80%이상 초과 시 디스크에 Spill한다.

Spill 하는 동안에도 메모리에는 계속해서 결과를 기록하며, 만약 Spill 하는 동안 메모리가 가득차면, 해당 맵 태스크는 Spill이 끝날때까지, block상태가 된다.

 

디스크로 Spill 하기 이전에, 리듀서의 개수에 맞게 파티션으로 나누고, 각 파티션 내 키를 기준으로 인메모리 정렬 수행. 만약 컴바이너 함수가 존재하면 정렬된 key-value를 가지고 수행한다.

 

메모리 버퍼가 Spill 한계치에 도달하면, 새로운 Spill 파일이 생성된다. 따라서, 한 맵태스크에서 여러개의 스필 파일이 존재할 수 있다. 맵 태스크가 종료되기 전에, 여러 스필파일은 단일 출력 파일로 병합되고 정렬된다.

 

최소 3개의 스필파일이 존재한다면, 출력파일을 쓰기 이전에 컴바이너 함수를 한번더 실행한다. 만약 2개라면, 컴바이너를 호출하는 오버헤드가 더큼으로 고려해야한다.

 

출력파일의 파티션은 HTTP를 통해 리듀서에게 전달.

 

리듀서는 어떻게 필요한 맵 출력 (파티션)을 알까?

맵태스크가 끝나면 하트비트 전송 매커니즘을 통해 어플리케이션 마스터에 알려준다. 리듀서 내 한 스레드는 맵 출력 호스트 정보를 주기적으로 마스터에게 요청하고 얻어낸다.

 

호스트는 맵리듀서가 맵출력을 회수해가도 어플리케이션 마스터로부터 삭제 요청이 오기전까지 삭제하지 않는다.

리듀스 태스크는 맵출력을 복사 스레드를 통해 복사해온다.

 

크기가 작다면 리듀스 태스크 JVM 메모리에 복사한다.

리듀스 태스크가 병합하는 과정은 라운드로 진행되고, 각 라운드마다 중간 파일이 생성된다.

 

리듀스함수의 출력은 HDFS에 저장된다.

맵리듀스 성능 향상을 위해서는, 셔플에 가능한 많은 메모리를 할당한다.

 

최선책은, 맵 리듀스 함수의 메모리 사용량을 줄이는 것이다.

맵 측면에서는, 디스크 스필이 많아지는 것을 피하는 것이 좋다.

리듀스 측면에서는, 중간파일들이 메모리에 위치할때 가장 빠르다.

반응형