하둡 맵리듀스 훑어보기

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

Upload: beom-kyun-choi

Post on 13-Jan-2015

3.216 views

Category:

Documents


2 download

DESCRIPTION

사내 발표용 하둡 맵리듀스 훑어보기 자료.

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)