'2016/07'에 해당되는 글 8건

  1. 2016.07.24 맵리듀스 튜닝에 대하여
반응형

하둡의 맵리듀스는 여러 튜닝 포인트가 존재한다. 하지만 기본적인 것은 네트워크로 전송되는 데이터를 감소 시키고, 디스크의 I/O를 최소화 시키는 것이다. 우선 맵리듀스가 동작하는 원리를 알아보자.


다음의 그림은 https://developer.yahoo.com/hadoop/tutorial/module4.html 에서 맵리듀스의 아키텍처를 설명한 그림이다.

기본적으로 맵 프로세스는 하나의 스필릿을 처리한다. 로컬에 있는 스플릿 하나가 하나의 맵 프로세스를 생성하게 되고, RecordReader 가 이 Split 에서 레코드를 읽어서 Key, Value 로 맵 프로세스에 전달하게 되는 것이다. 

 맵에서는 이 Key, Value를 가지고 또다른 Key, Value 조합으로 출력하게 되고, 파티셔너에 의해서 리듀스로 보내질 파티션으로 파일에 기록되게 된다. 

 맵 프로세스가 완료 되면, 이 파일들은 리듀스 프로세스가 생성되는 노드로 옮겨지게 되고, 리듀스 프로세스 결과는 다시 HDFS에 기록되게 된다.


 이 과정을 좀더 세분화해서 보면 (시작하세요! 하둡 프로그래밍의 그림 발췌)

  1) 입력 스플릿별로 하나의 맵 태스크가 실행된다.

  2) 맵 태스크는 메모리 버퍼 생성 후, 맵의 출력 데이터를 버퍼에 기록한다. 버퍼의 크기는 mapred-site.xml 에 정의된 io.sort.mb 속성에 정의되며 기본 값은 100 MB이다.

  3) 메모리 버퍼에 데이터가 어느정도(mapred-site.xml에 정의된 io.sort.spill.percent 속성) 차게 되면 해당 데이터를 로컬 디스크로 스필 한다. 스필할 때 데이터를 분리해서 리듀스 태스크와 일치되는 파티션을 생성한다. 파티션이 생성 될때 키 값에 따라 정렬을 수행한다. (정의된 compareTo 메서드 이용)

  4) 맵이 최종적으로 종료 되기 전에 스필 파일들은 하나의 정렬된 출력 파일로 병합된다. 병합될 스필 수는 io.sort.factor 기준으로 병합한다.  이 병합 파일은 리듀서가 HTTP로 접근할수 있도록 생성된다.

  5) 리듀스는 맵이 완료 되면 필요한 출력 데이터를 네트워크를 통해 복사한다.복사된 맵 출력 데이터는 리듀스용 메머리 버퍼에 복사된다. 메머리 버퍼 저장된 내용은 1) 버퍼가 일정한 크기가 도달할 때(임계치는 mapred-site.xml에 정의된 mapred.job.shuffle.merge.percent 속성 기준) 또는 메모리 버퍼에서 처리해야 할 파일 개수가 일정 개수에 도달할 때(mapred-site.xml 에 정의된 mapred.inmem.merge.threshold) 파일로 병합을 시도한다.

  6) 맵 출력 데이터가 모두 복사되면 해당 데이터를 병합한다. 병합은 라운드 방식으로 진행되며 병합 파일은 io.sort.fact의 값에 따라 병합한다. (예를 들어 30개의 맵 출력 데이터를 복사하고 io.sort.fact가 10으로 정의되어 있으면 각 라운드 당 파일 10개당 하나의 병합 파일을 만들게 되어 3개의 병합 파일이 생성된다.) 이 병합 파일은 하나의 파일로 병합되지 않고 즉시 리듀스의 입력 데이터로 전달된다.


1. 정렬 속성 튜닝(io.sort.x* 튜닝)

 맵 테스크는 스필 개수를 줄이는 것으로 성능을 개선할 수 있다. 로컬 디스크에 저장된 파일이 줄어들 수록 맵 출력 데이터의 병합, 네트워크 전송, 리듀스의 병합 작업 시간이 단축 될 수 있기 때문이다. 스필되는 파일을 줄이려면 스필 전 메모리 버퍼 크기인 is.sort.mb를 늘리면 된다. 메모리 버퍼가 커져서 로컬에 저장될 출력 데이터가 줄어 들기 때문이다.

 또한 io.sort.factor를 조절하여 병합할 파일 개수를 조정하여 병합되는 파일 개수를 줄일 수 있다.

 이 방법은 정렬 작업이 주가 되는 잡에서만 효과가 나타난다. 즉 잡의 속성에 따라서 성능이 안 좋아질 수 있다.


2. 콤바이너 클래스 적용

 콤바이너 클래스는 맵의 출력 데이터가 네트워크를 통해 리듀서에 전달되기 전에 매퍼의 출력 데이터의 크기를 줄이는 기능을 수행한다. 이전 포스팅 http://alnova2.tistory.com/777 에서 wordcount 에서 컴바이너 사용 전후의 성능 향상에 대하여 논한적이 있다.


3. 맵 출력 데이터 압축

 맵 출력 데이터를 압축해서 네트워크 트래픽을 줄이는 방법이다. YARN에는 mapreduce.map.output.compress 옵션을 true 로 설정하면 맵 태스크의 출력 데이터를 압축 파일로 생성한다. mapred.map.output.compress.codec 에 압축 방식을 설정할 수 있다. 압축된 파일은 네트워크를 통해 리듀스 태스크로 전송된 후, 압축 해제되어 리듀스 태스크의 입력 데이터로 사용된다.

 Gzip 의 경우 org.apache.hadoop.io.compress.GzipCodec로 Snappy 의 경우 org.apache.hadoop.io.compress.SnappyCodec 으로 적용 가능하다.


4. DFS 블록 사이즈 수정

 블록 사이즈에 따라서 스플릿 크기가 결정된다. 즉 파일 크기를 블록 사이즈로 나누면 맵 태스크 수를 계산할 수 있다. 맵 태스크가 많아지면 작업은 빨리 종료될 수 있다. hdfs-site.xml에 설정된 값으로 hdfs에 업로드 하는 전체 파일의 블록 사이즈가 정해지며, 특정 파일의 블록 사이즈만 변경할 경우 하둡의 distcp 옵션에 -Ddfs.block.size= 를 통해서 변경 가능하다.

 하지만 단순히 맵 태스크 수만을 가지고 성능 향상이 발생할 것이라고 기대해서는 안된다. 클러스터의 전체 코어 수와 메모리를 고려해서 최적화된 맵 태스크 수를 산정해야 한다.


반응형
Posted by alias
,