2016년 3월 21일 월요일

하둡(Hadoop) 기초 개념 정리.

'직접 해보는 하둡 프로그래밍'(한기용 지음)을 짧은 시간 동안 읽고, 프로젝트 시작 전 하둡 이해를 위해 책의 내용을 발췌하였다. 앞으로 프로젝트 간 하둡에 관하여 배운 것은 읽고 이해하기 쉽도록 정리하여 포스팅할 예정이다.


네임 노드 : HDFS에 저장되는 각종 파일과 디렉토리들의 메타정보를 관리하고 실제 데이터는 다수의 데이터노드에 분산 저장하는 역할을 담당합니다.

메타정보: 하나의 파일에 대해 그 이름과 소한 디렉토리 정보와 복제본개수의 수, 해당 파일을 구성하는 데이터 블록들의 ID 리스트와 각 블록별 저장 데이터노드의 이름들을 말한다.

2차 네임노드는 주기적으로 네임노드에게 체크포인트를 요청한다. 체크 포인트 사이에 혹시 발생할지 모르는 문제를 대비해서 체크포이트 사이의 모든 HDFS 트랜잭션은 모두 에디트로그라는 파일에 수록된다. 그리고 체크포인트 시마다 에디트로그의 내용은 리셋된다.

주기적으로 데이터노드가 네임노드에게 현재 상태를 보고하게 되는데 이를 하트비트라고 부른다.

맵이나 리듀스에서 로 사용되기 위해서는 WritableComparable이라는 인터페이스를 지원해야 한다.
맵이나 리듀스에서 밸류로 사용되기 위해서는 Writable이란 인터페이스를 구현해야 한다.
WritableComparable은 Writable 인터페이스를 포함한다.

Writable 인터페이스
Writable 인터페이스는 기본적으로 직렬화/역직렬화를 구현하는데 사용되는 메소드들을 갖고 있다.
하둡은 RPC(Remote Procedure Call)를 이용해서 클러스터 내의 노드들 간에 통신을 한다. 이때 함수 인자나 리턴값들을 네트워크를 타고 송수신하는데 이 Writable 인터페이스를 사용한다.
Writable 인터페이스 writereadFields라는 두 개의 메소드를 갖고 있다. (wrtie: 해당 객체가 직렬화될 때, readFields: 객체가 역직렬화될 때)

WritableComparable 인터페이스
WritaleComparable은 Writable에서 제공되는 메소드들에다가 객체들 간의 비교를 가능하게 해주기 위해 자바의 Comparable 인터페이스가 추가된 인터페이스이다.
Comparable 인터페이스에는 compareTo라는 메소드 하나가 존재하며 이는 결국 지금 객체와 인자로 들어온 객체를 비교하여 둘 사이의 순서를 정해주는 역할을 한다.

입력포멧 클래스
1)입력 파일을 어떻게 레코드들로 나누는지
2)각 레코드에서 키와 밸류를 어떻게 나누는지

TextInputFormat
한 레코드(라인)에서 키는 라인의 파일 오프셋(파일 선두에서부터)이고 타입은 LongWritable이다.
한 레코드(라인)에서 밸류는 라인 전체 스트링이 되며 타입은 Text이다.

KeyValueTextInputFormat
KeyValueTextInputFormat은 기본적으로 TextInputFormat과 같은 하나의 레코드(라인)을 해석할 때 키와 밸류 사이에 TAB 문자와 같은 분리자가 있다고 가정한다.

SequenceFileInputFormat
하둡의 고유 파일 포맷은 시퀀스 파일(Sequence FIle)이라는 것이다.
키나 밸류는 무슨 타입도 가능하지만 결국 앞서 해당 파일이 생성될 때 사용된 키와 밸류 타입을 사용해야 한다.
이 입력 포맷은 맵 파일(MapFile)을 읽는데도 사용할 수 있다.

시퀀스 파일은 하둡 고유의 바이너리 키/밸류 기반의 압축 지원 파일 포맷이며 키와 밸류는 어떤 타입이건 가능하다. 이는 하둡에서 여러 잡을 엮어(chaining) 작업할 때 반드시 사용해야하는 입력 포맷이다.

MultipleInputs
서로 다른 포맷의 입력 파일들을 다른 맵으로 처리하고 싶은 경우 사용
다른 두 종류의 입력 파일들 간에 공통의 키가 존재하고 같은 키를 갖는 레코드들끼리 묶어서 조인을 수행하고 싶은 경우에 사용.

입력 포맷이 역할
1)입력 파일을 InputSplit들로 나눈다.
2)하나의 InputSplit 내의 레코드들을 읽는 방법 제공

컴바이너
컴바이너는 미니 리듀서 혹은 로컬 리듀서라고 부르기도 한다.
맵 태스크의 출력에 리듀스 코드를 먼저 적용해서 리듀스로 넘어가야 하는 데이터의 크기를 줄이는 역할을 한다.
맵 태스크와 리듀스 태스크 간의 네트워크 통신량을 최소화하기 때문이다.
모든 잡에 컴바이너를 적용은 불가능하다. 작업의 순서를 달리해도 최종 결과물이 같은 잡이면 컴바이너를 적용할 수 있다. 수학적으로 표현하면 교환 법칙과 결합 법칙이 만족되는 잡이면 컴바이너를 적용할 수 있다.

파티셔너(Partitioner)
맵 태스크가 새로운 키/밸류 페어를 출력하면 이는 궁극적으로 특정 리듀스 태스크로 보내져야 합니다. 결과 레코드의 키값을 해싱해서 그 해싱값을 리듀스 태스크의 수로 나누어 그 레코드가 어느 리듀스 탯크로 갈지 정해진다. 같은 키를 갖는 레코드들은 같은 리듀스 태스크로 보내지도록 한다.

맵 출력 버퍼링
맵에서 출력된 레코드들은 파티셔너 클래스를 통해 파티션 번호를 따낸다. 그 후 바로 해당되는 리듀스 태스크로 보내지는 것이 아니라 일단 메모리 버퍼에 씌워졌다가 버퍼가 어느 정도 차면 그때 디스크 파일로 써진다. 맵 태스크가 종료될 때까지 이 과정을 반복하는데 종료 시에는 디스크로 존재하던 파일들을 모두 모아서 하나의 파일로 합병한다. 메모리 버퍼에 일단 쌓아두는 이유는 디스크에 바로바로 쓰는 것보다 어느 정도 모은 후 한 번에 몰아서 디스크에 쓰는 방식이 시간이 덜 걸리기 때문이다.

셔플링
하나의 맵 태스크가 종류되면 그때 리듀스 대스크들이 자신에게 해당하는 파티션의 데이터만 읽어가게 되는데 이때는 RPC등을 통하는 것이 아니라 그냥 HTTP를 통해 읽는다. 이 것을 셔플링이라고 부른다. HTTP를 통해 읽는다는 뜻은 태스크 트래커가 제공하는 HTTP 인터페이스를 통해 읽어 간다는 것입니다.

소팅
리듀스 태스크는 모든 맵 태스크들에서 읽어간 데이터들을 하나로 합병하는데 이때 맵 태스크 단에서 spill을 합병할 때처럼 이런 데이터 파일들의 수를 일정한 수 밑으로 유지하려고 한다. 합병이 끝나고 하나의 파일이 만들어지면 그때 레코드들의 키를 바탕으로 소팅을 한다. 소팅을 하는 이유는 그래야 어느 레코드들이 같은 키를 갖는지 알 수 있고 그래야 같은 키를 갖는 레코드들을 묶어서 하나의 리듀스 입력 레코드를 만들 수 있기 때문이다.


리듀스
run, setup, cleanup methods로 구성된다.
리듀스의 입력은 모든 맵 태스크들의 출력 레코드가 합쳐져서 만들어진다.
리듀스의 출력 레코드는 HDFS상에 저장된다.
아이덴터티 리듀서 클래스는 입력으로 들어온 레코드를 그대로 다시 출력해주는 역할을 한다. 아이덴터티 리듀서는 굉장히 많이 사용된다. 같은 키를 갖는 레코드들끼리 모아서 처리해야 할 필요가 없는 경우가 대표적이다. 예를 들어 이미지 변환이나 문서 분류기의 실행처럼 상대적으로 단순한 작업을 여러 서버에서 동시에 실행하고 싶은 경우(병렬 처리)에 사용된다.
reduce method에서 주의할 점은 인자로 넘어오는 밸류 리스트(Iterable<ValueType>)의 경우 한 번 밖에 스캔할 수 없다는 점이다. 레코드를 읽는 대로 바로 처리 하든지 내부적으로 자료구조를 만들어 상태를 저장해야 한다.


TextOutputFormat
텍스트 파일을 생성하고 출력 레코드 하나가 한 라인이 된다.

SequenceFileOutputFormat
이 포맷은 3가지 압축방식을 지원한다
1)BLOCK: 블록 내의 레코드들을 같이 압축
2)NONE: 압축을 하지 않는다.
3)RECORD:레코드 별로 압축. 기본 설정이 바로 레코드 별 압축.

MapFileOutputFormat
파일 기반의 맵으로 사실상 하나의 디렉토리로 구성되며 그 디렉토리 밑에 두 개의 파일이 존재한다. 하나는 맵의 데이터 파일로 모든 키와 밸류들이 들어가는데 키를 바탕으로 정렬이 된다. 다른 하나는 인덱스 파일로 키들의 일부를 저장하는데 목적은 데이터 파일을 순차적으로 뒤지지 않도록 해주는 것이다.

MultipleOutputs
여러가지 형태의 서로 다른 출력파일들을 명시적으로 만들어낼 수 있다.

이 포맷은 출력을 한 채널이 아닌 여러 채널로 할 수 있또록 해준다.


댓글 없음:

댓글 쓰기