하둡 맵리듀스 훑어보기

6,604 views

Published on

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

0 Comments
18 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
6,604
On SlideShare
0
From Embeds
0
Number of Embeds
1,389
Actions
Shares
0
Downloads
149
Comments
0
Likes
18
Embeds 0
No embeds

No notes for slide

하둡 맵리듀스 훑어보기

  1. 1. MapReduce 훑어보기 최범균 (2013-12-11)
  2. 2. 내용 ● MapReduce 이해 ○ 기본 흐름 ○ 하둡에서의 구조 ● 간단한 샘플 코드 ○ 국내 기상 데이터 이용 관측소 별 최고 온도 구하기 ○ 로컬 테스트/클러스터 실행 ● 리듀서 병렬 실행/콤바이너
  3. 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 입력 MR 프레임워크가 입력 파일로부터 (키, 값) 쌍을 맵 함수에 전달 Map 함수 (k1, v1) → (k2, v2) 셔플 (111, 10) (110, 30) (004, -20) (111, 40) (004, 5) (004, [-20, 5]) (110, [30]) (111, [10, 40]) Map 함수: (키, 값) 쌍을 입력받아 새로운 (키, 값) 쌍을 생성 MR 프레임워크가 Map의 출력을 키를 기준으로 묶고 정렬 Reduce 출력 Reduce 함 수 (k2, list (v2)) → (k3, v3) (004, -20) (110, 30) (111, 10) Reduct 함수: 셔플 결과를 입력으로 받고, (키, 값) 쌍을 생성
  4. 4. 하둡에서의 MR (하둡1 기준) 6. 데이터 위치 고려해 태스크 할당 1. Job ID 요청 잡클라이언트 2. HDFS에 잡 파일(jar 파일) 및 맵 작업 개수(스플릿) 정보 생성 (기본 10개의 복사본이 생성됨) 잡트래커 (JobTracker) 3. 잡 제출 4. 스플릿 정보 읽 어와 맵 및 리듀스 태스크 생성 8. HDFS에서 잡 파일(jar) 로컬 복 사 7.할당받은 맵 태스크 가져옴 맵 완료시 결과 통지 태스크트래커 (TaskTracker) 9. 태스크 JVM 실행 10. HDFS에서 데이터 읽어와 맵 실행 맵 결과는 로컬 파일에 보관 5. 데이터 위치 확인 9) 맵 결과 복사 태스크 JVM 네임노드 7) 할당받은 리듀스 태스크 가져옴 주기적으로 맵 출력 위치 문의 태스크트래커 (TaskTracker) 8) 태스크 JVM 실행 태스크 JVM 하둡 클러스터 10) 리듀스 실행
  5. 5. 셔플 과정 맵의 출력은 일단 메모리 버퍼에 보관 조건에 따라 파일로 내려 짐(spill) 스필 파일을 파 티션 별로 병합 (정렬 수행) spill 매퍼 버퍼 P1 각 매퍼에서 파 일 가져옴 병합된 파일을 생성 후, 리듀서 입력으로 사용 P1 병합됨 spill P2 P1 spill 버퍼 데이터를 파일에 보 관할 때, 파티션 별로 키 정렬 수행 (파티션: 리듀서의 개수) 다른 맵 노드에서 다른 리듀스 노드로 관련 자료: http://grepalex.com/2012/11/26/hadoop-shuffle-configurables/ 리듀서
  6. 6. 매퍼와 리듀서의 개수 ● 매퍼의 개수 ○ 입력 파일 / 스플릿 크기 ■ 기본: 스플릿 크기 = 블록 크기 ● 리듀서의 개수 ○ 잡 설정에서 개수 지정 ○ 병렬 실행을 고려해서 개수 지정 ● 파티셔너 ○ 매퍼의 결과를 분리할 때 사용 ○ 리듀서 개수에 맞게 매퍼 결과를 분리 ■ 기본: hash(key) % 리듀스개수
  7. 7. MR 프로그래밍 ● 데이터 준비 ○ 로컬에 테스트 용 파일 ○ HDFS에 실제 파일 ● 잡 구현 ○ 매퍼/리듀서 구현 ○ 콤바이너 구현 ● 테스트 ○ 단일 JVM 테스트 ○ 클러스터 테스트
  8. 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]
  9. 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()) ); // 맵의 출력 (값) } } }
  10. 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> { @Override protected 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)); // 리듀서의 결과 (키, 값) } }
  11. 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); } }
  12. 12. 로컬 실행: 설정 파일, 데이터 -- 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] -- 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>
  13. 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_0001 13/12/10 10:37:36 INFO mapred.LocalJobRunner: Waiting for map tasks 13/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_0 13/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 output 13/12/10 10:37:37 INFO mapred.LocalJobRunner: reduce > reduce 13/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 Framework 13/12/10 10:37:37 INFO mapred.JobClient: Map output materialized bytes=48 13/12/10 10:37:37 INFO mapred.JobClient: Map input records=4 13/12/10 10:37:37 INFO mapred.JobClient: Reduce shuffle bytes=0 13/12/10 10:37:37 INFO mapred.JobClient: Spilled Records=6 13/12/10 10:37:37 INFO mapred.JobClient: Map output bytes=36 13/12/10 10:37:37 INFO mapred.JobClient: Total committed heap usage (bytes)=325451776 13/12/10 10:37:37 INFO mapred.JobClient: Combine input records=0 13/12/10 10:37:37 INFO mapred.JobClient: SPLIT_RAW_BYTES=112 13/12/10 10:37:37 INFO mapred.JobClient: Reduce input records=3 13/12/10 10:37:37 INFO mapred.JobClient: Reduce input groups=2 13/12/10 10:37:37 INFO mapred.JobClient: Combine output records=0 13/12/10 10:37:37 INFO mapred.JobClient: Reduce output records=2 13/12/10 10:37:37 INFO mapred.JobClient: Map output records=3
  14. 14. 로컬 실행: 결과 -- output/part-r-000000 108→2.2 188→5.5
  15. 15. 클러스터 실행: 설정 파일, 데이터 -- 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> -- 파일 업로드 $ hadoop fs -copyFromLocal koreaweather.txt hdfs://10.50.0.xx2:9000/madvirus/koreaweather.txt
  16. 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 : 1 13/12/10 13:00:37 WARN util.NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable 13/12/10 13:00:37 WARN snappy.LoadSnappy: Snappy native library not loaded 13/12/10 13:00:40 INFO mapred.JobClient: Running job: job_201312100954_0002 13/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_0002 13/12/10 13:01:07 INFO mapred.JobClient: Counters: 26
  17. 17. 클러스터 실행(계속) 13/12/10 13:01:07 INFO mapred.JobClient: Job Counters 13/12/10 13:01:07 INFO mapred.JobClient: Launched reduce tasks=1 13/12/10 13:01:07 INFO mapred.JobClient: SLOTS_MILLIS_MAPS=25023 13/12/10 13:01:07 INFO mapred.JobClient: Total time spent by all reduces waiting after reserving slots (ms)=0 13/12/10 13:01:07 INFO mapred.JobClient: Total time spent by all maps waiting after reserving slots (ms)=0 13/12/10 13:01:07 INFO mapred.JobClient: Launched map tasks=3 13/12/10 13:01:07 INFO mapred.JobClient: Data-local map tasks=3 13/12/10 13:01:07 INFO mapred.JobClient: SLOTS_MILLIS_REDUCES=14655 13/12/10 13:01:07 INFO mapred.JobClient: FileSystemCounters 13/12/10 13:01:07 INFO mapred.JobClient: FILE_BYTES_READ=27462176 13/12/10 13:01:07 INFO mapred.JobClient: HDFS_BYTES_READ=183852236 13/12/10 13:01:07 INFO mapred.JobClient: FILE_BYTES_WRITTEN=43033108 13/12/10 13:01:07 INFO mapred.JobClient: HDFS_BYTES_WRITTEN=833 13/12/10 13:01:07 INFO mapred.JobClient: Map-Reduce Framework 13/12/10 13:01:07 INFO mapred.JobClient: Map input records=1814965 13/12/10 13:01:07 INFO mapred.JobClient: Reduce shuffle bytes=15338368 13/12/10 13:01:07 INFO mapred.JobClient: Spilled Records=3064358 13/12/10 13:01:07 INFO mapred.JobClient: Map output bytes=13142162 13/12/10 13:01:07 INFO mapred.JobClient: CPU time spent (ms)=21170 13/12/10 13:01:07 INFO mapred.JobClient: Total committed heap usage (bytes)=685572096 13/12/10 13:01:07 INFO mapred.JobClient: Combine input records=0 13/12/10 13:01:07 INFO mapred.JobClient: SPLIT_RAW_BYTES=342 13/12/10 13:01:07 INFO mapred.JobClient: Reduce input records=1098094 13/12/10 13:01:07 INFO mapred.JobClient: Reduce input groups=93 13/12/10 13:01:07 INFO mapred.JobClient: Combine output records=0 13/12/10 13:01:07 INFO mapred.JobClient: Physical memory (bytes) snapshot=816738304 13/12/10 13:01:07 INFO mapred.JobClient: Reduce output records=93 13/12/10 13:01:07 INFO mapred.JobClient: Virtual memory (bytes) snapshot=2920493056 13/12/10 13:01:07 INFO mapred.JobClient: Map output records=1098094
  18. 18. 클러스터 실행: 결과
  19. 19. 리듀서 병렬 실행 ● 동시에 실행할 리듀서 개수 지정 ○ 주의: 작업이 작으면 쪼개는 부하가 더 큼 public class MaxTempDriver2 extends Configured implements Tool { @Override public 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); } }
  20. 20. 파티셔너(Partitioner) ● 매퍼의 결과를 분리할 때 사용 ● 기본 파티셔너: 해시 이용 ○ hash(key) % 리듀서 개수 ● 데이터의 특성에 따라 커스텀 구현 가능 ○ 예, 연령대 별로 파티션을 나누고 싶을 때 ■ [0-10] → 1, [11-20] → 2, ...
  21. 21. 콤바이너(Combiner) ● 맵의 결과를 리듀스에 보내기 전에, 데이터를 최소화하기 위한 목적으로 사용 ● 리듀스와 동일한 함수 Map 출력 Map 함수 (k1, v1) → (k2, v2) Map 함수 (k1, v1) → (k2, v2) 맵 영역 병합 (111, 10) (110, 30) (004, -20) (111, 40) (004, 5) (004, [-20, 5]) (110, [30]) (111, [10, 40]) (111, 20) (005, 15) (111, 40) (005, 5) (005, [5, 15]) (111, [20,40]) Combine 함수 (k2, list (v2)) → (k3, v3) (004, [ 5]) (110, [30]) (111, [40]) Combine 함수 (k2, list (v2)) → (k3, v3) (005, [5]) (111, [20]) 리듀스 노드의 병합 결과 (004, [5]) (005, [5]) (111, [20,40]) Reduce 함 수 (k2, list (v2)) → (k3, v3)
  22. 22. 콤바이너 설정 public class MaxTempDriver3 extends Configured implements Tool { @Override public 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); } }
  23. 23. 콤바이너 적용 전/후 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 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
  24. 24. 예제 실행 중, 트러블슈팅 ● ● Cygwin에서 MR 로컬 실행 에러 (hadoop-1.2.1 사용시) ○ 에러 메시지 ■ Failed to set permissions of path: tmphadoopmadvirusmapredstagingmadvirus1210821488.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/
  25. 25. 하둡1 MR의 제약 ● 잡 트래커의 한계 ○ 잡 트래커가 자원 관리/잡 관리를 모두 수행 ○ 4,000 대, 동시 40,000 태스크 한계 ● 자원 활용 문제 ○ 노드 마다 맵/리듀스 태스크 개수 고정 ■ 기본 값: 맵 태스크 2개, 리듀스 태스크 2개 ■ 맵이 더 필요한 상황이어도 맵용 태스크 프로세스 를 더 할당할 수 없음 ● 하둡2에서 해결하려 함 ○ YARN (Yet Another Resource Negotiator)
  26. 26. 기타(앞으로 이해 필요..) ● Input/Output Format ○ File ○ Sequence ○ Map ● MR 튜닝 ○ http://www.slideshare.net/gruter/mapreduce-tuning ○ 결과 압축 (매퍼/리듀서) ● YARN (하둡2)

×