Top Banner
MapReduce 훑어보기 최범균 (2013-12-11)
26

하둡 맵리듀스 훑어보기

Jan 13, 2015

Download

Documents

beom kyun choi

사내 발표용 하둡 맵리듀스 훑어보기 자료.
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: 하둡 맵리듀스 훑어보기

MapReduce 훑어보기최범균 (2013-12-11)

Page 2: 하둡 맵리듀스 훑어보기

내용

● MapReduce 이해○ 기본 흐름○ 하둡에서의 구조

● 간단한 샘플 코드○ 국내 기상 데이터 이용 관측소 별 최고 온도 구하기○ 로컬 테스트/클러스터 실행

● 리듀서 병렬 실행/콤바이너

Page 3: 하둡 맵리듀스 훑어보기

MapReduce의 기본 흐름

111_10_…110_30_.004_-20_…111_40_…004_5_...

입력파일

(0, 111_10_…)(30, 110_30_….)(61, 004_-20_….)(87, 111_40_….)(103, 004_5_….)

Map 입력

Map 함수(k1, v1)

→(k2, v2)

(111, 10)(110, 30)(004, -20)(111, 40)(004, 5)

Map 출력

(004, [-20, 5])(110, [30])(111, [10, 40])

셔플

Reduce 함수

(k2, list(v2))→

(k3, v3)

(004, -20)(110, 30)(111, 10)

Reduce 출력

MR 프레임워크가입력 파일로부터(키, 값) 쌍을 맵 함수에 전달

Map 함수:(키, 값) 쌍을 입력받아새로운 (키, 값) 쌍을 생성

MR 프레임워크가Map의 출력을키를 기준으로 묶고 정렬

Reduct 함수:셔플 결과를 입력으로 받고, (키, 값) 쌍을 생성

Page 4: 하둡 맵리듀스 훑어보기

하둡 클러스터

하둡에서의 MR (하둡1 기준)

네임노드잡트래커

(JobTracker)

태스크트래커(TaskTracker)

잡클라이언트

태스크트래커(TaskTracker)

1. Job ID 요청

2. HDFS에 잡 파일(jar 파일) 및 맵 작업 개수(스플릿) 정보 생성(기본 10개의 복사본이 생성됨)

3. 잡 제출

4. 스플릿 정보 읽어와 맵 및 리듀스 태스크 생성

5. 데이터 위치 확인

6. 데이터 위치 고려해 태스크 할당

7.할당받은 맵 태스크 가져옴맵 완료시 결과 통지

8. HDFS에서 잡 파일(jar) 로컬 복사

태스크 JVM

9. 태스크 JVM 실행

10. HDFS에서 데이터 읽어와 맵 실행맵 결과는 로컬 파일에 보관

7) 할당받은 리듀스 태스크 가져옴주기적으로 맵 출력 위치 문의

태스크 JVM

8) 태스크 JVM 실행

9) 맵 결과복사

10) 리듀스 실행

Page 5: 하둡 맵리듀스 훑어보기

셔플 과정

매퍼 P1

P2

버퍼

spill

spill

spill

맵의 출력은 일단 메모리 버퍼에 보관조건에 따라 파일로 내려짐(spill)

버퍼 데이터를 파일에 보관할 때, 파티션 별로 키 정렬 수행(파티션: 리듀서의 개수)

관련 자료: http://grepalex.com/2012/11/26/hadoop-shuffle-configurables/

P1

P1

다른 맵 노드에서

스필 파일을 파티션 별로 병합 (정렬 수행)

병합됨 리듀서

각 매퍼에서 파일 가져옴

병합된 파일을 생성 후, 리듀서 입력으로 사용

다른 리듀스 노드로

Page 6: 하둡 맵리듀스 훑어보기

매퍼와 리듀서의 개수

● 매퍼의 개수○ 입력 파일 / 스플릿 크기

■ 기본: 스플릿 크기 = 블록 크기● 리듀서의 개수

○ 잡 설정에서 개수 지정○ 병렬 실행을 고려해서 개수 지정

● 파티셔너○ 매퍼의 결과를 분리할 때 사용○ 리듀서 개수에 맞게 매퍼 결과를 분리

■ 기본: hash(key) % 리듀스개수

Page 7: 하둡 맵리듀스 훑어보기

MR 프로그래밍

● 데이터 준비○ 로컬에 테스트 용 파일○ HDFS에 실제 파일

● 잡 구현○ 매퍼/리듀서 구현○ 콤바이너 구현

● 테스트○ 단일 JVM 테스트○ 클러스터 테스트

Page 8: 하둡 맵리듀스 훑어보기

예제 프로그래밍: 관측소 별 최고 기온 구하기

● 데이터 형식○ station: 관측소 번호○ year/month/date: 관측일○ meanTemp/maxTemp/minTemp/rainFall

■ 평균 기온, 최고 기온, 최저 기온, 강수량■ 데이터가 없으면 null

● 데이터 양○ 1960.01.01~2012.12.31 까지 국내 관측 데이터

■ 약 150M (Big은 아님, 예제용)[station=108, year=1960, month=1, date=1, meanTemp=-1.6, maxTemp=2.2, minTemp=-5.2, rainfall=null][station=108, year=1960, month=1, date=2, meanTemp=-1.9, maxTemp=1.2, minTemp=-5.6, rainfall=0.4]…[station=102, year=1960, month=3, date=15, meanTemp=null, maxTemp=null, minTemp=null, rainfall=null]…...[station=188, year=2012, month=12, date=31, meanTemp=2.0, maxTemp=5.5, minTemp=0.2, rainfall=1.8]

Page 9: 하둡 맵리듀스 훑어보기

매퍼 코드package weather;

import java.io.IOException;

import org.apache.hadoop.io.DoubleWritable;import org.apache.hadoop.io.LongWritable;import org.apache.hadoop.io.Text;import org.apache.hadoop.mapreduce.Mapper;

public class MaxTempMapper extends Mapper<LongWritable, Text, Text, DoubleWritable> { private Parser parser = new Parser(); @Override protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException { parser.parse(value.toString()); if (parser.getMaxTemp() != null) { context.write( new Text(parser.getStation()), // 맵의 출력 (키) new DoubleWritable(parser.getMaxTemp()) ); // 맵의 출력 (값) } }

}

Page 10: 하둡 맵리듀스 훑어보기

리듀서 코드package weather;

import java.io.IOException;

import org.apache.hadoop.io.DoubleWritable;import org.apache.hadoop.io.Text;import org.apache.hadoop.mapreduce.Reducer;

public class MaxTempReducer extends Reducer<Text, DoubleWritable, Text, DoubleWritable> {

@Overrideprotected void reduce(Text key, Iterable<DoubleWritable> values, Context context)

throws IOException, InterruptedException {double maxValue = -273;for (DoubleWritable val : values) {

if (maxValue < val.get())maxValue = val.get();

}context.write(key, new DoubleWritable(maxValue)); // 리듀서의 결과 (키, 값)

}

}

Page 11: 하둡 맵리듀스 훑어보기

잡 실행기public class MaxTempDriver extends Configured implements Tool { @Override public int run(String[] args) throws Exception { Job job = new Job(getConf(), "Max Temperature"); job.setJarByClass(getClass()); FileInputFormat.addInputPath(job, new Path(args[0])); // 매퍼 입력 파일 FileOutputFormat.setOutputPath(job, new Path(args[1])); // 리듀서 출력 디렉토리 job.setMapperClass(MaxTempMapper.class); job.setReducerClass(MaxTempReducer.class); job.setOutputKeyClass(Text.class); // 리듀서 출력 키 타입 job.setOutputValueClass(DoubleWritable.class); // 리듀서 출력 값 타입 return job.waitForCompletion(true) ? 0 : 1; }

public static void main(String[] args) throws Exception { int exitCode = ToolRunner.run(new MaxTempDriver(), args); System.exit(exitCode); }}

Page 12: 하둡 맵리듀스 훑어보기

로컬 실행: 설정 파일, 데이터

-- hadoop-local.xml<?xml version="1.0" encoding="utf-8" ?><configuration>

<property><name>fs.default.name</name><value>file:///</value>

</property>

<property><name>mapred.job.tracker</name><value>local</value>

</property></configuration>

-- weather-sample.txt[station=108, year=1960, month=1, date=1, meanTemp=-1.6, maxTemp=2.2, minTemp=-5.2, rainfall=null][station=108, year=1960, month=1, date=2, meanTemp=-1.9, maxTemp=1.2, minTemp=-5.6, rainfall=0.4][station=102, year=1960, month=3, date=15, meanTemp=null, maxTemp=null, minTemp=null, rainfall=null][station=188, year=2012, month=12, date=31, meanTemp=2.0, maxTemp=5.5, minTemp=0.2, rainfall=1.8]

Page 13: 하둡 맵리듀스 훑어보기

로컬 실행: Job 실행$ export HADOOP_CLASSPATH=target/classes$ hadoop weather.MaxTempDriver -conf conf/hadoop-local.xml weather-sample.txt output 13/12/10 10:37:36 INFO mapred.JobClient: Running job: job_local872299175_000113/12/10 10:37:36 INFO mapred.LocalJobRunner: Waiting for map tasks13/12/10 10:37:36 INFO mapred.LocalJobRunner: Starting task: attempt_local872299175_0001_m_000000_0...13/12/10 10:37:36 INFO mapred.LocalJobRunner: Finishing task: attempt_local872299175_0001_m_000000_013/12/10 10:37:36 INFO mapred.LocalJobRunner: Map task executor complete....13/12/10 10:37:37 INFO mapred.Task: Task:attempt_local872299175_0001_r_000000_0 is done. And is in the process of commiting...13/12/10 10:37:37 INFO output.FileOutputCommitter: Saved output of task 'attempt_local872299175_0001_r_000000_0' to output13/12/10 10:37:37 INFO mapred.LocalJobRunner: reduce > reduce13/12/10 10:37:37 INFO mapred.Task: Task 'attempt_local872299175_0001_r_000000_0' done.13/12/10 10:37:37 INFO mapred.JobClient: map 100% reduce 100%13/12/10 10:37:37 INFO mapred.JobClient: Job complete: job_local872299175_0001...13/12/10 10:37:37 INFO mapred.JobClient: Map-Reduce Framework13/12/10 10:37:37 INFO mapred.JobClient: Map output materialized bytes=4813/12/10 10:37:37 INFO mapred.JobClient: Map input records=413/12/10 10:37:37 INFO mapred.JobClient: Reduce shuffle bytes=013/12/10 10:37:37 INFO mapred.JobClient: Spilled Records=613/12/10 10:37:37 INFO mapred.JobClient: Map output bytes=3613/12/10 10:37:37 INFO mapred.JobClient: Total committed heap usage (bytes)=32545177613/12/10 10:37:37 INFO mapred.JobClient: Combine input records=013/12/10 10:37:37 INFO mapred.JobClient: SPLIT_RAW_BYTES=11213/12/10 10:37:37 INFO mapred.JobClient: Reduce input records=313/12/10 10:37:37 INFO mapred.JobClient: Reduce input groups=213/12/10 10:37:37 INFO mapred.JobClient: Combine output records=013/12/10 10:37:37 INFO mapred.JobClient: Reduce output records=213/12/10 10:37:37 INFO mapred.JobClient: Map output records=3

Page 14: 하둡 맵리듀스 훑어보기

로컬 실행: 결과

-- output/part-r-000000108→2.2188→5.5

Page 15: 하둡 맵리듀스 훑어보기

클러스터 실행: 설정 파일, 데이터

-- 파일 업로드$ hadoop fs -copyFromLocal koreaweather.txt hdfs://10.50.0.xx2:9000/madvirus/koreaweather.txt

-- conf-cluster.xml<?xml version="1.0" encoding="utf-8" ?><configuration>

<property><name>fs.default.name</name><value>hdfs://10.50.0.xx2:9000</value>

</property>

<property><name>mapred.job.tracker</name><value>10.50.0.xx2:9001</value>

</property></configuration>

Page 16: 하둡 맵리듀스 훑어보기

클러스터 실행$ unset HADOOP_CLASSPATH

$ hadoop jar target/weather-0.0.1-SNAPSHOT.jar weather.MaxTempDriver \ -conf conf/hadoop-cluster.xml \ hdfs://10.50.0.202:9000/madvirus/koreaweather.txt \ hdfs://10.50.0.202:9000/madvirus/output

13/12/10 13:00:37 INFO input.FileInputFormat: Total input paths to process : 113/12/10 13:00:37 WARN util.NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable13/12/10 13:00:37 WARN snappy.LoadSnappy: Snappy native library not loaded13/12/10 13:00:40 INFO mapred.JobClient: Running job: job_201312100954_000213/12/10 13:00:41 INFO mapred.JobClient: map 0% reduce 0%13/12/10 13:00:49 INFO mapred.JobClient: map 66% reduce 0%13/12/10 13:00:59 INFO mapred.JobClient: map 66% reduce 22%13/12/10 13:01:00 INFO mapred.JobClient: map 100% reduce 22%13/12/10 13:01:07 INFO mapred.JobClient: map 100% reduce 100%13/12/10 13:01:07 INFO mapred.JobClient: Job complete: job_201312100954_000213/12/10 13:01:07 INFO mapred.JobClient: Counters: 26

Page 17: 하둡 맵리듀스 훑어보기

클러스터 실행(계속)13/12/10 13:01:07 INFO mapred.JobClient: Job Counters13/12/10 13:01:07 INFO mapred.JobClient: Launched reduce tasks=113/12/10 13:01:07 INFO mapred.JobClient: SLOTS_MILLIS_MAPS=2502313/12/10 13:01:07 INFO mapred.JobClient: Total time spent by all reduces waiting after reserving slots (ms)=013/12/10 13:01:07 INFO mapred.JobClient: Total time spent by all maps waiting after reserving slots (ms)=013/12/10 13:01:07 INFO mapred.JobClient: Launched map tasks=313/12/10 13:01:07 INFO mapred.JobClient: Data-local map tasks=313/12/10 13:01:07 INFO mapred.JobClient: SLOTS_MILLIS_REDUCES=1465513/12/10 13:01:07 INFO mapred.JobClient: FileSystemCounters13/12/10 13:01:07 INFO mapred.JobClient: FILE_BYTES_READ=2746217613/12/10 13:01:07 INFO mapred.JobClient: HDFS_BYTES_READ=18385223613/12/10 13:01:07 INFO mapred.JobClient: FILE_BYTES_WRITTEN=4303310813/12/10 13:01:07 INFO mapred.JobClient: HDFS_BYTES_WRITTEN=83313/12/10 13:01:07 INFO mapred.JobClient: Map-Reduce Framework13/12/10 13:01:07 INFO mapred.JobClient: Map input records=181496513/12/10 13:01:07 INFO mapred.JobClient: Reduce shuffle bytes=1533836813/12/10 13:01:07 INFO mapred.JobClient: Spilled Records=306435813/12/10 13:01:07 INFO mapred.JobClient: Map output bytes=1314216213/12/10 13:01:07 INFO mapred.JobClient: CPU time spent (ms)=2117013/12/10 13:01:07 INFO mapred.JobClient: Total committed heap usage (bytes)=68557209613/12/10 13:01:07 INFO mapred.JobClient: Combine input records=013/12/10 13:01:07 INFO mapred.JobClient: SPLIT_RAW_BYTES=34213/12/10 13:01:07 INFO mapred.JobClient: Reduce input records=109809413/12/10 13:01:07 INFO mapred.JobClient: Reduce input groups=9313/12/10 13:01:07 INFO mapred.JobClient: Combine output records=013/12/10 13:01:07 INFO mapred.JobClient: Physical memory (bytes) snapshot=81673830413/12/10 13:01:07 INFO mapred.JobClient: Reduce output records=9313/12/10 13:01:07 INFO mapred.JobClient: Virtual memory (bytes) snapshot=292049305613/12/10 13:01:07 INFO mapred.JobClient: Map output records=1098094

Page 18: 하둡 맵리듀스 훑어보기

클러스터 실행: 결과

Page 19: 하둡 맵리듀스 훑어보기

리듀서 병렬 실행

● 동시에 실행할 리듀서 개수 지정○ 주의: 작업이 작으면 쪼개는 부하가 더 큼

public class MaxTempDriver2 extends Configured implements Tool {

@Overridepublic int run(String[] args) throws Exception {

….Job job = new Job(getConf(), "Max Temperature");job.setJarByClass(getClass());...job.setOutputKeyClass(Text.class);job.setOutputValueClass(DoubleWritable.class);job.setNumReduceTasks(3);return job.waitForCompletion(true) ? 0 : 1;

}

public static void main(String[] args) throws Exception {int exitCode = ToolRunner.run(new MaxTempDriver2(), args);System.exit(exitCode);

}}

Page 20: 하둡 맵리듀스 훑어보기

파티셔너(Partitioner)

● 매퍼의 결과를 분리할 때 사용● 기본 파티셔너: 해시 이용

○ hash(key) % 리듀서 개수● 데이터의 특성에 따라 커스텀 구현 가능

○ 예, 연령대 별로 파티션을 나누고 싶을 때■ [0-10] → 1, [11-20] → 2, ...

Page 21: 하둡 맵리듀스 훑어보기

콤바이너(Combiner)

● 맵의 결과를 리듀스에 보내기 전에, 데이터를 최소화하기 위한 목적으로 사용

● 리듀스와 동일한 함수

Map 함수(k1, v1)

→(k2, v2)

(111, 10)(110, 30)(004, -20)(111, 40)(004, 5)

Map 출력 맵 영역 병합

Reduce 함수

(k2, list(v2))→

(k3, v3)

(004, [-20, 5])(110, [30])(111, [10, 40])

Combine함수

(k2, list(v2))→

(k3, v3)

(004, [ 5])(110, [30])(111, [40])

Map 함수(k1, v1)

→(k2, v2)

(111, 20)(005, 15)(111, 40)(005, 5)

(005, [5, 15])(111, [20,40])

Combine함수

(k2, list(v2))→

(k3, v3)

(005, [5])(111, [20])

(004, [5])(005, [5])(111, [20,40])

리듀스 노드의 병합 결과

Page 22: 하둡 맵리듀스 훑어보기

콤바이너 설정public class MaxTempDriver3 extends Configured implements Tool {

@Overridepublic int run(String[] args) throws Exception {

...Job job = new Job(getConf(), "Max Temperature");job.setJarByClass(getClass());...job.setMapperClass(MaxTempMapper.class);job.setReducerClass(MaxTempReducer.class);job.setCombinerClass(MaxTempReducer.class);

job.setOutputKeyClass(Text.class);job.setOutputValueClass(DoubleWritable.class);return job.waitForCompletion(true) ? 0 : 1;

}

public static void main(String[] args) throws Exception {int exitCode = ToolRunner.run(new MaxTempDriver3(), args);System.exit(exitCode);

}}

Page 23: 하둡 맵리듀스 훑어보기

콤바이너 적용 전/후Counters: 26 Job Counters Launched reduce tasks=1 SLOTS_MILLIS_MAPS=24569 Total time spent by all reduces waiting after reserving slots (ms)=0 Total time spent by all maps waiting after reserving slots (ms)=0 Launched map tasks=3 Data-local map tasks=3 SLOTS_MILLIS_REDUCES=13623 FileSystemCounters FILE_BYTES_READ=9509 HDFS_BYTES_READ=183852236 FILE_BYTES_WRITTEN=248129 HDFS_BYTES_WRITTEN=833 Map-Reduce Framework Map input records=1814965 Reduce shuffle bytes=5184 Spilled Records=1049 Map output bytes=13142162 CPU time spent (ms)=20330 Total committed heap usage (bytes)=685375488 Combine input records=1098094 SPLIT_RAW_BYTES=342 Reduce input records=370 Reduce input groups=93 Combine output records=370 Physical memory (bytes) snapshot=808636416 Reduce output records=93 Virtual memory (bytes) snapshot=2920337408 Map output records=1098094

Counters: 26 Job Counters Launched reduce tasks=1 SLOTS_MILLIS_MAPS=25023 Total time spent by all reduces waiting after reserving slots (ms)=0 Total time spent by all maps waiting after reserving slots (ms)=0 Launched map tasks=3 Data-local map tasks=3 SLOTS_MILLIS_REDUCES=14655 FileSystemCounters FILE_BYTES_READ=27462176 HDFS_BYTES_READ=183852236 FILE_BYTES_WRITTEN=43033108 HDFS_BYTES_WRITTEN=833 Map-Reduce Framework Map input records=1814965 Reduce shuffle bytes=15338368 Spilled Records=3064358 Map output bytes=13142162 CPU time spent (ms)=21170 Total committed heap usage (bytes)=685572096 Combine input records=0 SPLIT_RAW_BYTES=342 Reduce input records=1098094 Reduce input groups=93 Combine output records=0 Physical memory (bytes) snapshot=816738304 Reduce output records=93 Virtual memory (bytes) snapshot=2920493056 Map output records=1098094

Page 24: 하둡 맵리듀스 훑어보기

예제 실행 중, 트러블슈팅● Cygwin에서 MR 로컬 실행 에러 (hadoop-1.2.1 사용시)

○ 에러 메시지■ Failed to set permissions of path: \tmp\hadoop-

madvirus\mapred\staging\madvirus1210821488\.staging to 0700○ 처리 방법

■ https://github.com/congainc/patch-hadoop_7682-1.0.x-win● 원격 HDFS 파일 시스템 접근 에러 관련

○ 에러 메시지■ org.apache.hadoop.security.AccessControlException: Permission

denied: user=madvirus, access=WRITE, inode="/":ndap:supergroup:drwxr-xr-x

○ 처리 방법■ 권한 변경으로 처리

● $ hadoop fs -chmod 777 hdfs://bt1:9000/

Page 25: 하둡 맵리듀스 훑어보기

하둡1 MR의 제약

● 잡 트래커의 한계○ 잡 트래커가 자원 관리/잡 관리를 모두 수행○ 4,000 대, 동시 40,000 태스크 한계

● 자원 활용 문제○ 노드 마다 맵/리듀스 태스크 개수 고정

■ 기본 값: 맵 태스크 2개, 리듀스 태스크 2개■ 맵이 더 필요한 상황이어도 맵용 태스크 프로세스를 더 할당할 수 없음

● 하둡2에서 해결하려 함○ YARN (Yet Another Resource Negotiator)

Page 26: 하둡 맵리듀스 훑어보기

기타(앞으로 이해 필요..)

● Input/Output Format○ File○ Sequence○ Map

● MR 튜닝○ http://www.slideshare.net/gruter/mapreduce-tuning○ 결과 압축 (매퍼/리듀서)

● YARN (하둡2)