BigDATA/Hadoop

03. 맵리듀스 시작하기 - 맵-리듀스 개념

태하팍 2014. 9. 1. 14:34
반응형

회사 위키에 정리해서 복사&붙여넣기를 하니..깨져서 나오는 현상이 있어서 하루패드의 마크다운 기능을 사용해보았습니다.

 

목 차

맵-리듀스 개념
맵-리듀스 아키텍처

1.맵-리듀스 개념

  1. 맵-리듀스 패턴(Scatter-Gather의 한 형태[Hohpe and Woolf])은 클러스터에서 많은 장비의 장점을 활용해 처리하며서 데이터가 위치한 노드에서 최대한 많은 처리가 실행되도록 작업을 조직하는 방법이다. 맵-리듀스는 구글의 맵-리듀스 프레임워크[Dean and Ghemawat]로 유명해졌다. 맵-리듀스란 이름은 함수형 프로그래밍 언어에서 컬렉션에 대해 맵과 리듀스 연산을 하는 데서 영감을 얻은 것이다.

  2. 맵리듀스 프로그래밍 모델은 단순하게 맵(map)과 리듀스(reduce)라는 두 개의 메소드로 다음과 같은 동작을 수행합니다.

     : (k1, v1) → list(k2, v2)

    리듀스 : (k2, list(v2))→ list(k3, v3)

* 맵 메소드는 키(k1)와 값(v1)으로 구성된 데이터를 입력받아 이를 가공하고 분류한 후 새로운 키(k2)와 값(v2)으로 구성된 목록을 출력 합니다.
이때 맵 메소드가 반복해서 수행되다 보면 새로운 키(k2)를 가지는 여러 개의 데이터가 만들어집니다. 리듀스 메소드의 새로운 키(k2)로 그룹핑된 값의 목록(list(v2))를 입력 데이터로 전달받습니다. 이후 값의 목록(list(v2))에 대한 집계 연산을 실행해 새로운 키(k3)와 값(v3)으로 구성된 목록을 생성 합니다.

예를 들어서 맵리듀스로 "read a book"과 "write a book"이라는 두 줄의 문장으로 구성된 텍스트 파일을
입력받아 전체 글자 수를 계산해 보겠습니다.

 (1) 맵-리듀스는 입력 파일을 키와 값 형식의 데이터로 분류 합니다. 위의 예제에서는 키는 라인 번호 이고 값은 문장 입니다.

 (2) 키와 값 형식의 데이터는 맵 메소드의 입력 데이터로 전달 됩니다.

 (3) 맵 메소드는 라인 번호별로 문장을 체크해 키에 해당하는 글자별로 글자 수를 출력합니다.

 (4) 맵-리듀스는 맵 메소드의 출력 데이터를 정렬하고, 병합합니다.

 (5) 4번의 결과가 리듀스 메소드의 입력 데이터로 전달 됩니다.

 (6) 리듀스 메소드는 새로운 키인 글자별로 각 글자 수를 합산해서 출력 합니다.

 (7) 리듀스 메소드의 출력 데이터를 하둡 파일 시스템에 저장 합니다.

그림_a) 맵리듀스 개념 예제

 

Tip) 굿팁!

  • 맵 작업은 한 집합에 대해서만 적용할 수 있고, 리듀스 작업은 한 키에 대해서만 적용할 수 있다. 이러한 제약조건에서도 잘 동작하려면 프로그램의 구조를 다르게 생각해야 한다.
  • 맵-리듀스는 클러스터에서 계산의 병령화를 쉽게 해주는 패턴이다.
  • 맵 작업은 집합으로부터 데이터를 읽어 관련된 키-값 쌍으로 압축한다. 맵은 한번에 레코드 하나만 읽으므로 병렬화될 수 있고 해당 레코드를 저장한 노드에서 실행된다.
  • 리듀스 작업은 한 키에 대해 맵 작업의 결과로 나온 많은 값을 취해 출력 하나로 요약한다. 각 리듀스 함수는 한 키에 대해 작용하기 때문에 키로 병렬화할 수 있다.

2. 맵-리듀스 아키텍처

  1. 시스템 구성

맵-리듀스 시스템은 클라이언트, 잡트래커, 태스크트래커로 구성 됩니다.

* 클라이언트 
사용자가 실행한 맵-리듀스 프로그램과 하둡에서 제공하는 맵리듀스 API를 의미 합니다. 사용자는 맵-리듀스 API로 맵-리듀스 프로그램을 개발하고, 개발한 프로그램을 하둡에서 실행할 수 있습니다.

* 잡트래커(JobTracker)
클라이언트가 하둡으로 실행을 요청하는 맵-리듀스 프로그램은 잡(Job)이라는 하나의 작업 단위로 관리됩니다. 잡트래커는 하둡 클러스터에 등록된 전체 잡의 스케줄링을 관리하고 모니터링 합니다.
전체 하둡 클러스터에서 하나의 잡트래커가 실행되며(죽으면???), 보통 하둡의 네임노드 서버에서 실행됩니다. 
※ 반드시 네임노드 서버에서 실행할 필요는 없음. 페이스북 같은경우 잡트래커를 별개의 서버에서 동작하도록 구성 함.

또한 사용자가 새로운 잡을 요청하면 잡트래커는 잡을 처리하기 위해 몇 개의 맵과 리듀스를 실행할지 계산합니다. 이때 태스크트래커는 잡트래커의 작업 수행 요청을 받아 맵리듀스 프로그램을 실행합니다. 잡트래커와 태스크트래커는 하트비트(heardbeat)라는 메소드로 네트워크 통신을 하면서 태스크트래커의 상태와 작업 실행 정보를 주고받게 됩니다. 만약 태스크트래커에 장애가 발생하면 잡트래커는 다른 대기 중인 태스크트래커를 찾아 태스크를 재실행하게 됩니다.

* 태스크트래커(TaskTracker)
태스크트래커는 사용자가 설정한 맵-리듀스 프로그램을 실행하며, 하둡의 데이터노드에서 실행되는 데몬입니다. 태스크트래커는 잡트래커의 작업을 요청받고, 잡트래커가 요청한 맵과 리듀스 개수만큼 맵 태스크(map task)와 리듀스 태스크(Reduce Task)를 생성 합니다. 여기서 맵 태스크와 리듀스 태스크란 사용자가 설정한 맵과 리듀스 프로그램입니다.


2.맵-리듀스 작동 방식

"복잡하지만 이해하여 BOA요!"

그림_c) 맵-리듀스의 작동방식

1) 맵리듀스잡실행

사용자는 잡에 대한 실행 정보를 설정한 후(직접 개발을 해야 무슨소린지 알수 있을듯..ㅋㅋ) waitForCompletion 메소드를 호출해 잡을 실행합니다.

※ 잡 제출 시 waitForCompletion()은 2초에 한번씩 진행 과정을 조사하여 변경이 생기면 콘솔로 보여준다.


2) 신규 잡 제출(Job Submission)

잡 인터페이스에서는 새로운 잡클라이언트 객체가 생성되고, 이 객체가 잡트래커에 접속해 잡을 실행해줄 것을 요청 합니다. 이때 잡트래커는 잡클라이언트에게 새로운 Job ID를 반환합니다.(잡트래커 상에서 getNewJobId()호출) Job ID를 전달받은 잡클라이언트는 사용자가 설정한 출력 경로를 확인하는데, 이미 존재하는 경로를 입력했으면 에러가 발생하고 맵리듀스 프로그램이 종료됩니다.


3) 입력 스플릿 생성

잡클라이언트는 잡의 입력 데이터에 대한 입력 스플릿(input split)을 계산합니다. 당연히 입력 경로를 잘못 입력해서, 입력 스플릿을 계산할 수 없다면 에러가 발생하고 맵리듀스 프로그램은 종료됩니다. 입력 스플릿이 계산되고 나면 입력 스플릿 정보, 설정 파일, 맵리듀스 JAR파일을 HDFS에 저장하고, 잡트래커에게 잡을 시작할 준비가 끝났음을 알려줍니다.

  • 입력 스플릿이란?
    하나의 맵에서 처리해야 하는 입력 파일의 크기 입니다. 하둡은 맵리듀스 잡의 입력 데이터를 입력 스플릿이라는 고정된 크기의 조각으로 분리합니다. 하둡은 생성된 입력 스플릿마다 맵 태스크를 하나씩 생성 합니다. 그리고 입력 스필릿을 해당 맵 태스크의 입력 데이터로 전달합니다. 입력 데이터가 HDFS의 기본 블록 사이즈인 64MB보다 큰 경우에만 입력 스플릿이 생성됩니다. ※ 입력 스플릿의 크기는 하둡 환경설정 파일인 mapred-site.xml에서 수정할 수 있습니다. 입력 스플릿의 최소 바이트 크기는 mapred.min.split.size 프로퍼티이며, 기본값은 0 바이트 입니다.


4) 잡 할당

잡 클라이언트의 메시지를 받은 잡트래커는 잡을 큐에 등록하고, 잡스케줄러가 큐(Queue)에 가져와서 초기화 합니다. 초기화 후 잡스케줄러는 잡클라이언트가 HDFS에 등록한 입력 스플릿 정보를 가져와 입력 스플릿의 개수만큼 맵 태스크를 생성하고 ID를 부여합니다. 태스크트래커는 주기적으로 잡트래커의 하트비트(heartbeat)라는 메소드를 호출해서 자신의 상태정보를 잡트래커에게 알려줍니다. 잡트래커는 하트비트 메소드를 통해 전달된 저옵를 이용해 어떠한 태스크트래커에게 태스크 실행을 요청할지 결정한 후, 해당 태스크트래커에 태스크 실행을 요청합니다.


5) 매퍼 실행

태스크트래커는 잡트래커가 할당해준 맵 태스크를 실행 합니다. 맵 태스크는 사용자가 설정한 매퍼 클래스이며, 입력 스필릿은 키와 값의 형태로 맵 태스크의 입력 데이터로 전달됩니다. 또한 맵 태스크는 맵 메소드의 정의돼 있는 로직을 실행하고, 출력 데이터를 메모리 버퍼에 저장합니다. 이때 파티셔너는 해당 출력 데이터가 어떤 리듀스 태스크에 전달돼야 할지를 결정하고, 그에 맞는 파티션을 지정해줍니다. 파티션에서는 메모리에 있는 데이터를 키에 따라 정렬한 후, 로컬 디스크에 저장해줍니다. 파티션별로 디스크 저장이 완료되면 이 파일들은 하나의 출력 파일로 병합되고 정렬 됩니다.


6) 정렬, 병합

리듀스 태스크는 사용자가 설정한 리듀서 클래스 입니다. 리듀스 태스크는 자신이 필요한 맵 태스크의 모든 출력 데이터가 있어야만 작업을 실행할 수 있습니다. 그렇다면 어떻게 맵 태스크의 출력 데이터를 복사할까요? 맵 태스크는 출력이 완료되면 자신을 실행한 태스크트래커에게 작업이 정상적으로 끝났다고 알려줍니다. 이 메시지를 받은 태스크트래커는 잡트래커에게 해당 맵 태스크의 상태와 맵 태스크의 출력 데이터 경로를 알려줍니다. 리듀스 태스크에서는 주기적으로 잡트래커에게 맵 태스크의 출력 데이터 경로를 물어보며, 출력 데이터 경로가 정상적으로 조회되면 해당 출력 데이터를 로컬 노드로 복사합니다. 이때 파일이 크면 디스크로 복사하고, 작을 경우 메모리로 복사 합니다.


7) 리듀서 실행

리듀스 태스크는 모든 맵 태스크의 출력 데이터를 복사한 후, 맵 태스크의 출력 데이터를 병합합니다. 병합이 완료되면 리듀스 메소드를 호출해서 분석 로직을 실행 합니다.


8) 출력 데이터 저장

리듀스 태스크는 출력 데이터를 HDFS에 part-nnnn이라고 저장합니다. 여기서 nnnn은 파티션 ID를 의미하며, 00000부터 1씩 증가됩니다.


시작하세요! 하둡 프로그래밍과 하둡완벽 가이드 책을 맵-리듀스 부분을 병행하며 보고 있는데..책의 장단점들이 있네요 ㅎㅎㅎㅎ 

# 이전 글 
2014/08/27 - [BigDATA/Hadoop] - 01. 하둡 소개 
2014/08/28 - [BigDATA/Hadoop] - 02. About HDFS..

#참고 문헌 :
1. 시작하세요! 하둡프로그래밍 - 정재화 지음
2. 빅데이터 세상으로 떠나는 간결한 안내서 NoSQL - 마틴 파울러 지음
3. 하둡 완벽 가이드 개정3판

반응형