하둡으로 데이터 분석하기
- Hadoop/맵리듀스 데이터분석하기
- 2021. 2. 1.
하둡으로 데이터 분석하기
█ awk는 행 기반 데이터를 처리하기 위한 전통적인 유닉스 도구다.
압축된 연도별 파일을 반복적으로 돌며 처음에는 해당 연도를 출력하고 그 후 awk를 이용해서 각 파일을 처리한다. awk스크립트는 데이터에서 두 개의 필드(기온과 특성코드)를 추출한다. 기온(문자열)에 0을 더하면 그 값은 정수형으로 변환된다. 다음에는 기온이 유효한 값(9999는 NCDC 데이터셋에서 누락된 값을 의미)을 가지는지, 특성 코드가 그 측정값을 신뢰할 수 있다고 보는지 점검한다. 측정된 값에 문제가 없다면 현재 최고 기온과 비교하여 새로운 값이 더 높으면 최고 기온을 변경한다. END 영역은 파일에 있는 모든 행이 처리된 후에 실행되는데, 최종 최고 기온을 출력한다.
█ 20세기의 전체 데이터를 한 대의 EC2 고성능 CPU XL(High-CPU Extra Large) 인스턴스에서 실행해본 결과 42분이 걸렸다.
█ 처리속도를 높이기 위해 프로그램의 각 부분을 병렬로 수행할 필요가 있다. 하지만 이 방식에는 몇 가지 문제가 있다
첫째, 일을 동일한 크기로 나눈다는 것이 언제나 쉽고 명확한 것은 아니다. 결국 전체 수행 시간은 가장 긴 파일을 처리하는 프로세스의 처리 시간에 의해 결정된다. 대안 중 하나는 전체 입력 파일을 고정길이의 데이터 청크로 나누고 각 청크를 하나의 프로세스에 할당하는 것이다.
둘째, 독립적인 프로세스의 결과를 모두 합치는데 더 많은 처리가 필요할 수도 있다. 이 예제에서 특정 연도의 데이터는 몇 개의 청크로 나뉠 가능성이 높고, 각 청크는 독립적으로 처리된다. 우리는 각각의 청크에서 최고 기온을 찾고, 마지막 단계에서 연도별 최고 기온을 구할 수 있다.
셋째, 단일 머신의 처리 능력은 여전히 한계가 있다. 단일 머신에서 여러 개의 프로세서로 처리할 수 있는 최적의 수행 시간이 20분이라면 이것이 바로 머신의 한계다. 처리 시간은 더 이상 빨라질 수 없다. 여러 대의 머신을 사용할 때는 코디네이션(coordination, 협력과 조정)과 신뢰성의 범주에 속하는 요소를 추가로 고려해야 한다. 잡의 전체 과정을 누가 조율하고 프로세스의 실패를 어떻게 처리할지 고민해야 한다. 병렬로 처리하는 것이 쉬워 보이지만 실제로는 매우 복잡하다.
이러한 이슈를 처리하기 위해 하둡과 같은 프레임워크를 사용하는 것은 큰 도움이 된다.
█ 자바 맵리듀스
맵 함수, 리듀스 함수, 잡을 구동하기 위한 코드를 볼 필요가 있다. 맵 함수는 추상 map() 메서드를 정의하는 Mapper 클래스로 구현된다.
맵 함수
Mapper 클래스는 제네릭generic 타입으로, 네 개의 정규 타입 매개변수(입력키, 입력값, 출력키, 출력값)을 가진다. 예제에서 입력키는 long integer 타입의 오프셋, 입력값은 한 행의 내용, 출력키는 연도, 출력값은 기온(정수)이다. 하둡은 최적화된 네트워크 직렬화를 위해 (내장 자바 타입 대신) 자체적으로 기본 타입 셋을 제공한다. 이러한 타입 클래스는 org.apache.hadoop.io 패키지에서 찾아볼 수 있다. 여기서 우리는 자바 Long에 해당하는 LongWritable, 자바 String에 해당하는 Text, 자바 Integer에 해당하는 IntWritable을 사용한다.
map() 메서드의 입력으로 하나의 키와 하나의 값이 전달된다. 우리는 한 행의 Text 입력값을 자바 String으로 변환하고, 원하는 컬럼을 추출하기 위해 substring()메서드를 사용한다.
또한 map()메서드는 출력을 위해 Context의 인스턴스를 제공한다. 예제에서 연도는 Text객체로(키로 사용되기 때문에), 기온은 IntWritable 객체로 기록된다. 기온이 존재하고 측정된 값에 대한 특성 코드가 유효하다면 출력 레코드를 기록한다.
리듀스 함수: 리듀스 함수는 Reducer를 사용하여 정의한다. 맵 함수의 정의와 비슷하다.
리듀스 함수 역시 입력과 출력 타입을 규정하기 위해 네 개의 정규 타입 매개변수를 사용한다. 리듀스 함수의 입력 타입은 맵 함수의 출력 타입이었던 Text, IntWritable과 짝을 이룬다. 예제에서 리듀스 함수의 출력 타입은 Text와 IntWritable이며, Text에는 연도를, IntWritable에는 해당 연도의 기온값을 모두 비교하여 가장 높은 기온을 기록한다.