1. 맵리듀스 프로그래밍의 특징
- 데이터 셋은 Key, Value의 집합이며 변경 불가(immutable)
- 데이터 조작은 map과 reduce 두 개의 오퍼레이션으로만 가능
- 이 두 오퍼레이션은 항상 하나의 쌍으로 연속으로 실행됨
- 이 두 오퍼레이션의 코드를 개발자가 채워야함
- 나머지는 시스템이 다 알아서 함
- 맵리듀스 시스템이 Map의 결과를 Reduce 단으로 모아줌
- 이 단계를 보통 셔플링이라 부르며 네트워크 단을 통한 데이터 이동이 생김
- 같은 키의 값들을 묶어서 밸류를 묶어주는 게 reduce 이 과정이 셔플링
- map이 돌아가는 서버와 reduce 돌아가는 서버가 다르기 때문에, 네트워크를 통한 데이터 전송
- 이 셔플링 과정이 길어질 경우, 데이터 처리 과정이 길어짐
- 맵 리듀스 프로그래밍의 핵심 : 맵과 리듀스
- Map : (k, v) -> [(k',v')]
- 입력은 시스템에 의해 주어지며 입력으로 지정된 HDFS 파일에서 넘어옴
- 키, 밸류 페어를 새로운 키, 밸류 페어 리스트로 변환(transformation)
- 출력 : 입력과 동일한 키, 밸류 페어를 그대로 출력해도 되고, 출력이 없어도 됨
- Reduce(k', [v1', v2', v3', v4',...]) -> (k", v")
- 입력은 시스템에 의해 주어짐
- 맵의 출력 중 같은 키를 갖는 키/밸류 페어를 시스템이 묶어서 입력으로 넣어줌
- 키와 밸류 리스트를 새로운 키, 밸류 페어로 변환
- SQL의 GROUP BY와 흡사
- 출력이 HDFS에 저장됨
- 입력은 시스템에 의해 주어짐
- Map : (k, v) -> [(k',v')]
- MapReduce 프로그램 동작 예시
- Word Count
- 보통 이럴 때는 key를 랜덤 값을 주고, 텍스트를 value로 줘서 단어별로 카운트를 한다.
- 해당 출력을 시스템이 모아서, 같은 키를 같는 레코드들을 하나의 레코드로 묶어서 reduce의 입력으로 넣는다.
- 이 과정에서 셔플링이 발생하는데, 특정 리듀스로 데이터가 너무 몰리는 data skew가 발생한다.
- Map 코드
public static class TokenizerMapper
extends Mapper<Object, Text, Text, IntWritable>{
private final static IntWritable one = new IntWritable(1);
private Text word = new Text();
public void map(Object key, Text value, Context context
) throws IOException, InterruptedException {
StringTokenizer itr = new StringTokenizer(value.toString());
while (itr.hasMoreTokens()) {
word.set(itr.nextToken());
context.write(word, one);
}
}
}
- Reduce 코드
public static class IntSumReducer
extends Reducer<Text,IntWritable,Text,IntWritable> {
private IntWritable result = new IntWritable();
public void reduce(Text key, Iterable<IntWritable> values,
Context context
) throws IOException, InterruptedException {
int sum = 0;
for (IntWritable val : values) {
sum += val.get();
}
result.set(sum);
context.write(key, result);
}
}
- MapReduce : Shuffling and Sorting
- Shuffling
- Mapper의 출력을 Reducer로 보내주는 프로세스를 말함
- 전송되는 데이터의 크기가 크면 네트워크 병목을 초래하고 시간이 오래 걸림
- Sorting
- 모든 Mapper의 출력을 Reducer가 받으면 이를 키별로 Sorting
- Shuffling
- MapReduce : Data Skew
- 각 태스크가 처리하는 데이터 크기에 불균형이 존재한다면?
- 병렬처리의 큰 의미가 없음. 가장 느린 태스크가 전체 처리 속도를 결정
- 특히 Reducer로 오는 나눠지는 데이터의 크기는 큰 차이가 있을 수 있음
- Group By나 Join등이 이에 해당
- 처리 방식에 따라 Reducer의 수에 따라 메모리 에러가 발생할 수 있음
- 데이터 엔지니어가 고생하는 이유 중에 하나
- 빅데이터 시스템에는 이 문제가 모두 존재
- 각 태스크가 처리하는 데이터 크기에 불균형이 존재한다면?
2. 맵리듀스 프로그래밍의 한계
- MapReduce 프로그래밍의 문제점
- 낮은 생산성
- 프로그래밍 모델이 가진 융통성 부족(2가지 오퍼레이션만 지원)
- 데이터 모델과 오퍼레이션에 제약이 많음
- 모든 입출력이 디스크를 통해 이뤄짐
- 큰 데이터 배치 프로세싱에 적합
- 튜닝/최적화가 쉽지 않음
- 예) 데이터 분포가 균등하지 않은 경우
- shuffling 이후에 Data Skew가 발생하기 쉬움
- Reduce 태스크 수를 개발자가 지정해주어야함
- 배치 작업 중심
- 기본적으로 Low Latency가 아니라 Throughput에 초점이 맞춰짐
- 낮은 생산성
- MapReduce의 대안들의 등장
- 더 범용적인 대용량 데이터 처리 프레임워크들의 등장
- YARN, Spark
- SQL의 컴백 : HIVE, Presto등이 등장
- Hive
- MapReduce위에서 구현됨. throughput에 초점. 대용량 ETL에 적합
- 디스크 사용
- Presto
- Low latency에 초점. 메모리를 주로 사용. Adhoc 쿼리에 적합
- AWS Athena가 Presto 기반
- 요즘은 Presto로 대용량 ETL을 하는데에 아무 문제가 없음
- 요즘은 둘 다 단점을 보완하면서, 두 개가 비슷해짐
- Hive
- 더 범용적인 대용량 데이터 처리 프레임워크들의 등장
'데이터 엔지니어링 > Spark' 카테고리의 다른 글
6. Spark(개발환경 옵션, Local Standalone, 활용 Demo) (0) | 2023.07.28 |
---|---|
5. Spark 프로그램 구조(Spark Session 생성, 환경변수) (1) | 2023.07.11 |
4. Spark 프로그래밍 : DataFrame(데이터처리, 동작구조) (0) | 2023.07.11 |
3. 빅데이터 처리와 Spark 소개(Spark 소개, Spark 프로그램 실행 옵션) (0) | 2023.07.10 |
1. 빅데이터 처리와 Spark 소개(빅데이터 정의, 하둡 이론 등) (2) | 2023.07.10 |