etc2011. 6. 29. 10:09
- 맵리듀스는 데이터 처리를 위한 프로그래밍 모델이다.
- 기상 데이터셋 (설명 p.43~44)
- 처리 속도를 높이기 위하여, 프로그램의 각 부분을 병렬로 수행할 필요가 있다.
: 하나의 서버에서 이용할수 있는 모든 하드웨어 스레드별로 다른 프로세스를 실행시켜 다른 연도별 파일을 처리할 수 있다.
몇가지 문제점이 있는데,
  • 동일한 크기로 잡을 나눈다는것이 항상 쉽고 명백한 것만은 아니다.
    : 연도별 파일크기가 일반적으로 다양하기 때문에 몇몇 프로세스들은 다른 것들보다 훨씬 먼저 끝날것이다. 결국 전체 수행결과는 가장 긴 파일에 의해 좌우 될것이다.
    (하나의 대안은 입력 파일들을 고정크기의 데이터 청크 들로 나우고 프로세스별로 각 덩어리를 할당하는 방식)
  • 독립적인 프로세스로부터 결과를 조합하는데 더 많은 처리가 필요할 수 있다.
    : 연도별 결과는 다른 연도별 결과와는 무관하기때문에 모든 결과를 갖다 붙이고 연도별로 정렬함으로써 조합될수 있다. 고정크기의 데이터 청크 방식을 사용한다면 특정연도에 대한 데이터는 전형적으로 몇개의 데이터 청크들로 나누어질것이고, 각각 독립적으로 처리. 그리고 각데이터 청크 단위로 최고기온을 얻을것이며, 연도별 최고기온은 마지막 단계에서 찾게 될것이다.
  • 단일 서버의 처리능력은 여전히 한정되어 있다.
    : 처리할수 있는 최적의 수행시간의 제한, 단일 서버의 용량 등.

- 결과적으로 처리과정을 병렬화하는것이 그럴듯 해 보일지라도, 실제로는 엄청 복잡. 이러한 이슈들을 처리하기 위해 하둡과 같은 프로임워크를 사용하는것은 대단한 이득이다.

[ 하둡으로 데이터 분석하기 ]
- 맵과 리듀스
- 맵리듀스는 맵 단계와 리듀스 단계로 처리과정을 나누어 작업한다.
- 맵 단계에서 입력은(기상청) 원본데이터.
- 맵 함수는 분석 대상(인 연도와 기온)을 추출한다.
: 연도별로 최고기온을 찾아주는 리듀스 함수의 준비단계에 불과하다. 또한 잘못된 레코드를 제거하는 역할도 수행한다.
-  맵 함수 (설명 p.48)
: 키들은 파일 내에서 몇 번째 라인인지 나타내는 오프셋. 맵 함수에서는 무시된다.
맵 함수는 연도와 기온을 추출.
맵 함수의 출력은 리듀스 함수로 보내지기 전에 맵리듀스 프레임워크에서 처리한다.
프레임워크는 키를 중심으로 키/값 쌍들을 정렬하고 그룹을만든다.
따라서 리듀스 함수는 다음과 같은 입력을 받게 된다.
연도별로 그 해 측정한 모든 기온값이 리스트로 출력. 이제 모든 리듀스 함수는 리스트 전체를 순환하며 최고 측정값을 추출.


- 자바 맵리듀스 (설명 p.49)
- 예제 2-3 최고기온을 구하는 Mapper 예제
: 맵 함수는 map() 메소드를 선언하는 Mapper 인터페이스로 구현한다.
Mapper 인터페이스는 map 함수에 네 개의 정규 타입 매개변수들(입력키, 입력값, 출력키, 출력값)을 가지는 제네릭 타입.
입력키는 long integer 타입의 오프셋,
입력값은 한라인을 나타내는 내용,
출력키는 연도,
출력값은 기온(정수) 이다.

(하둡은 최적화된 네트워크 직렬화를 위해 자체적으로 기본 타입 셋을 제공한다.)

- 예제 2-4 최고기온을 구하는 Reducer 예제
: 리듀스 함수의 출력타입들은 지금까지 찾아진 가장 높은 기온과 입력된 각 기온을 반복해서 비교함으로써 구해진 각 연도와 해당 연도의 최고기온을 구한다.

- 예제 2-5 기상청 데이터셋으로부터 최고기온을 찾는 응용프로그램
: 맵리듀스 잡 
잡 명세서는 어떻게 잡을 수행 할지를 결정.
하둡 클러스터에서 잡을 실행할 때에는 소스 코드를 JAR 파일로 묶어야 한다(하둡은 클러스터에 JAR 파일을 배치할 것이다).
명시적으로 JAR 파일의 이름을 정하기 보다는 JobConf 생성자에 클래스 하나를 할당할 수 있으며, 하둡은 그 클래스를 포함하는 JAR 파일을 찾아서 클러스터에 배치할 수 있다.
addInputPath(): 입력경로
setOutputPath(): 출력파일 저장할 디렉터리 (해당 디렉터리는 잡을 수행하기 전에는 존재하지 않아야 함)

setMapperClass(): 맵 타입 설정
setReducerClass(): 리듀스 타입 설정
setOutputKeyClass(): 맵 함수 출력타입 지정
setOutputValueClass(): 리듀스 함수 출력타입 지정
JobClient.runJob(): 잡 실행
출력은 output 디렉터리로 쓰였고, 리듀스당 하나의 출력 파일을 생성.


- 새로운 자바 맵리듀스 API (하둡 릴리즈 0.20.0)

  • 새로운 API 에서는 인터페이스였던 Mapper 와 Reducer 가 이제는 추상 클래스로 바뀌었다.
  • 새로운 API 는 org.apache.hadoop.mapreduce 패키지(그리고 서브패키지) 안에 있다. 이전 API 는 org.apache.hadoop.mapred 에서 찾을수 있다.
  • 새로운 API 는 MapContext 는 기본적으로 JobConf, OutputCollecter, Reporter 의 역할을 통합
  • 새로운 API 는 'push', 와 'pull' 방식의 반복자를 모두 지원한다. 순차적 처리보다는 배치성 레코드를 처리할 때, 'pull' 방식이 더 유용하다.
  • 환경 설정 파일이 통합되었다. 잡 설정은 Configuration 을 통해 처리.
  • 새로운 API 에서 잡 제어는 더는 존재하지 않는 JobClient 보다 Job 클래스를 통해 수행된다.

: 맵 출력을 위해서는 part-m-nnnn, 리듀스 출력을 위해서는 part-r-nnnn 으로 생성
새로운 API 를 사용하기 위해 재작성된 MaxTemperature 응용프로그램. 차이점 ( p.57~58)

[ 분산형으로 확장하기 ]
: 단순화를 위해 로컬 파일시스템의 파일들을 사용. 확장을 위하여 데이터를 HDFS 에 저장해야 한다.
- 데이터 흐름
- 맵리듀스 잡: 클라이언트가 수행하려는 작업단위. 이것은 입력 데이터, 맵리듀스 프로그램, 설정 정보로 구성. 하둡은 잡을 맵 태스크와 리듀스 태스크로 나뉘어 실행
- 잡 실행
: 하나의 잡 트래커와 다수의 태스크 트래커. 두가지 유형의 노드가 존재.
- 잡 트래커: 태스크 트래커들이 수행할 태스크들을 스케쥴링함으로써 시스템 전체에서 모든 잡들이 수행되도록 조절.
- 태스크 트래커: 태스크들을 수행하고 각 잡의 전체 경과를 하나의 레코드로 유지하는 경과보고서를 잡 트래커에 보낸다. (실패시 다른 태스크 트래커에 다시 스케쥴 한다)
- 하둡은 맵리듀스 잡의 입력을 입력 스플릿이라는 고정크기 조각들로 나눈다. 하둡은 각 스플릿마다 하나의 맵 태스크를 생성하고, 그 스플릿에 있는 각 레코드를 사용자 정의맵 함수로 정의한다.
(전체입력을 통째로 처리하는 시간보다, 많은 스플릿을 통하여 분할된 조각을 처리하는 시간이 더 짧게 걸린다. 스플릿 크기가 작을 수록 부하분산에 더 좋은 효과가 난다. 같은 성능의 서버에서도 프로세스들이 실패하거나 여러잡이 동시에 실행되기 때문에 부하 분산은 바람직하다. 부하 분산 효과는 스플릿들이 세분화 될수록 커진다. 분할크기를 너무 작게하면, 분할 관리와 맵 태스크 생성을 위한 오버헤드가 전체 잡 실행시간을 압도하기 시작한다. 기본적으로 64MB 의 HDFS 블록을 사용하는 추세. 하둡은 HDFS 내의 입력 데이터가 있는 노드에서 맵 태스크를 실행할 때에 가장 잘 작동. 최적의 스플릿 크기가 HDFS 블록크기와 같아야 하는 이유는, 그 블록 크기가 단일 노드에 저장된다고 확신할 수 있는 가장 큰 입력 크기이기 때문.)
- 맵 태스크의 결과는 HDFS 가 아닌 로컬 디스크에 저장된다. 이유는 맵의 결과는 리듀스가 최종결과를 생성하기 위해 사용하는 중간결과물, 잡이 완료되면 맵의 결과는 버려도 되기 때문이다.
- 단일 리듀스 태스크의 맵리듀스 데이터 흐름 (p. 60)
: 리듀스 태스크의 개수는 입력크기에 따라 결정되지 않고 독립적으로 지정. (p.268 잡에 대한 리듀스 태스크의 개수를 어떻게 선택하는지)
- 다중 리듀스 태스크의 맵리듀스 데이터 흐름 (p.61)
: 리듀스가 여럿일 때, 맵 태스크는 각 리듀스 태스크만큼 파티션을 생성하고 맵의 결과를 그 파티션으로 분배시킨다. (파티셔닝 알고리즘은 일반적으로 해시 함수를 이용해 버켓에 분배해주는 기본적인 파티셔너를 사용하지만 사용자 정의 파티셔닝 함수도 사용할 수 있다.)
맵과 리듀스 태스크들의 사이의 데이터흐름을 비공식적으로 '셔플' 이라하는지 이유를 보여준다. 튜닝을 통해서 잡 실행 시간에 상당한 영향을 줄수 있다. (p.251 '셔플과 정렬')
- 리듀스 태스크 없는 맵리듀스 데이터 흐름 (p.62)
: 처리 과정을 완전히 병렬로 수행할 수 있기 때문에 셔플이 필요 없는 경우에 적합. 이 경우 유일한 외부 노드 간 데이터 전송은 맵 태스크가 HDFS 에 결과를 저장할 때다.

- 컴바이너 함수
: 맵의 결과를 입력으로 처리(컴바이너 함수의 출력이 결국 리듀스 함수의 입력이 된다.)
많은 맵리듀스 잡들은 클러스터 내에서 이용할 수 있는 대역폭이 제한적이기 때문에 맵과 리듀스 태스크 간 데이터 전송을 최소화 할 필요가 있다. 컴바이너 함수가 최적화에 관련되어 있기 때문에 하둡은 특정 맵의 결과 레코드에 컴바이너를 얼마나 호출해야 할지에 대한 기능을 제공하지 않는다.
- 컴바이너 함수규약은 사용할 수 있는 함수형을 제한한다.
첫번째 맵의 결과
(1950, 0)
(1950, 20)
(1950, 10)
두번째 맵의 결과
(1950, 25)
(1950, 15)
하나의 리스트에 담아 리듀스 함수로 전달
(1950, [0, 20, 10, 25, 15])
리듀스 결과
(1950, 25)
각맵의 출력에서 최고기온을 찾기 위해 컴바이너 함수를 마치 리듀스 함수처럼 사용할 수 있다.
(각 맵에 대한 컴바이너의 결과값을 리스트에 담아 다음과 같이 리듀스로 전달)
(1950, [20, 25])
단순하게, 맵-컴바이너-리듀스 함수는 다음과 같은 값으로 호출
max(0, 20, 10, 25, 15) = max(max(0, 20, 10), max(25, 15)) = max(20, 25) = 25
- 컴바이너 함수가 리듀스 함수를 대체할 수 있는 것은 아니다.
: 맵과 리듀스 사이에서 셔플할 데이터의 양을 줄이는 데에 도움된다.
- 컴바이너 함수를 작성하기 (p.64)
: 컴바이너 함수는 Reducer 인터페이스를 사용하여 정의된다.
응용프로그램을 위해 MaxTemperatureReducer 에 있는 리듀서 함수와 같은 소스코드를 사용.


[ 하둡 스트리밍 ]
: 사용자 프로그램 사이의 인터페이스로 유닉스 표준 스트림을 사용한다. 표준입력으로 부터 읽고 표준출력으로 쓸 수 있는 어떠한 언어라도 맵리듀스 프로그래밍용으로 사용가능
스트리밍은 라인단위로 데이터를 처리. 맵의 출력 키/값 쌍은 하나의 탭으로 구분된 라인으로 쓰인다. 이듀스 함수의 입력도 표준입력으로 전달된 탭으로 구분된 키/값 쌍과 같은 포멧.
- 루비 (맵 함수, 리듀스 함수- 작성 설명 p.66)
- hadoop 명령으로 실행하기
: hadoop 명령어는 스트리밍 옵션을 지원하지 않는다. 스트리밍 프로그램의 옵션들은 입출력 경로, 맵과 리듀스 스크립트를 지정한다. 큰 데이터셋을 클러스터에서 실행할 때, -combiner 옵션을 사용하여 컴바이너를 설정해야한다. 버젼 0.21.0 부터, ㅋ머바이너는 어떠한 스트리밍 명령어로도 작성될 수 있다. 이전 버전에서는 컴바이너는 자바로 작성되어야 했고, 자바에 얽매이지 않는 차선책으로 매퍼에서 컴바이닝을 수작업으로 하는것이 일반적. 클러스터에서 스트리밍 프로그램을 실행할 때(?) 클러스터로 스크립트들을 전송하기 위하여 -file 옵션을 사용하는 점을 주목하라.
- 파이썬
: 스트리밍은 표준입력으로부터 읽고, 표준출력으로 쓸 수 있는 어떠한 프로그래밍 언어라도 지원이 가능.
- 하둡 파이프 (예제 p.70~71)
: 하둡 맵리듀스를 위한 C++ 인터페이스의 이름이다. 맵과 리듀스 코드사이의 통신을 위해 표준 입출력을 사용하는 스트리밍과 다르게, 파이프는 태스크 트래커가 C++ 맵 또는 리듀스 함수를 실행하는 프로세스와 직접 통산히기 위하여 소켓을 통신 채널로 사용한다. 맵과 리듀스 함수들은 HadoopPipes 네임스페이스에 속하고 각각 map(), reduce() 메소드의 인터페이스를 제공하는 Mapper 와 Reducer 클래스를 상속함으로써 정의된다. C++ 인터페이스에서의 키와 값들은 STL(Standard Template Library) 로 표현되는 바이트 버퍼다. 파이프는 HDFS 가 실행되고 있어야만 작동하는 하둡의 분산 캐시 메커니즘에 의존하기 때문에 독립 실행형(로컬) 모드로는 실행되지 않는다.
- 컴파일 및 실행 (p.72~73)

Posted by 깜장눈썹