2012년 2월 26일 일요일

맵리듀스 타입과 포맷

  1. 맵리듀스 타입
  1. map: (K1, V1) → list(K2, V2)
combine: (K2, list(V2)) → list(K2, V2)
partition: (K2, V2) → 정수
reduce: (K2, list(V2)) → list(K3, V3)
  1. 리듀스의 입력 타입은 맵의 출력 타입과 같아야 함
  2. 컴바인의 타입은 리듀스의 타입과 같은 경우가 많음
  3. 파티션은 중간 키와 값(K2, V2)에 대하여 파티션 번호를 반환하며 키에 의해서 결정됨
  4. 267P 맵리듀스 타입 설정 표 참조
  5. 기본적인 맵리듀스 잡 - input/ouput만 설정하는 최소 설정과 동일한 명시적인 JobConf 구현
  1. conf.setInputFormat(TextInputFormat.class)
  2. conf.setNumMapTasks(1)
  1. 실제 맵 태스크 개수는 입력 데이터의 크기, 파일의 블록 크기로 결정됨
  1. conf.setMapperClass(IdentityMapper.class)
  1. 입력키와 값을 변경 없이 그대로 출력함
  2. 맵 입력키/출력키, 입력값/출력값이 서로 같은 타입으로 설정되어야 정상적으로 동작함
  1. conf.setMapRunnerClass(MapRunner.class)
  1. MapRunnable의 기본 구현체
  2. 각 레코드를 순차적으로 읽어서 매퍼의 map()메소드를 호출함
  1. conf.setMapOutputKeyClass(LongWritable.class)
  2. conf.setMapOutputValueClass(Text.class)
  3. conf.setPartitionerClass(HashPartitioner.class)
  1. 레코드의 키를 해시해서 해당 레코드가 어떤 파티션에 속하는지 결정함
  2. 각 파티션은 리듀스 태스크에 의해 분산 처리됨
  3. 잡 내에서 파티션 개수는 리듀스 태스크 개수와 같음
  4. return (key.hashCode() & Integer.MAX_VALUE) % numPartitions
  1. conf.setNumReduceTasks(1)
  1. 최적의 리듀서 개수는 클러스터 내의 리듀서 슬롯의 총 개수와 연관이 있음
  2. 리듀서수를 슬롯의 총 개수보다 약간 작게 설정하는 것이 좋음
  3. 슬롯의 총 개수 = 클러스터 노드의 개수 * mapred.tasktracker.reduce.tasks.maximum속성값
  1. conf.setReducerClass(IdentityReducer.class)
  1. 입력키와 값을 변경 없이 그대로 출력함
  1. conf.setOutputKeyClass(LongWritable.class)
  2. conf.setOutputValue(Text.class)
  3. conf.setOutputFormat(TextOutputFormat.class)
  1. 기본 스트리밍 잡
  1. 입력포맷이 TextInputFormat이면 스트리밍 출력의 키와 값은 모두 Text이므로 기본 IdentityMapper를 사용하면 안되고 다른 mapper를 제공해야 함
  2.  command 예시 :
hadoop jar $HADOOP_INSTALL/contrib/streaming/hadoop-*-streaming.jar
-input input/ncdc/sample.txt
-output output
-mapper /bin/cat
-inputformat org.apache.hadoop.mapred.TextInputFormat
(-partitioner org.apache.hadoop.mapred.lib.HashPartitioner
-numReduceTasks 1
-reducer org.apache.hadoop.mapred.lib.IdentityReducer
-outputformat org.apache.hadoop.mapred.TextOutputFormat)
  1. 스트리밍 키와 값
  1. 키와 값은 구분자로 분리함 (기본 - ‘\t’)
  2. 구분자로 분리되는 필드들을 더하여 키로 정할 수 있음
  3. 입력포맷과 출력포맷을 구분하여 설정함
  4. 275P 스트리밍 분리자 속성 표 참조
  1. 입력 포맷
  1. 스플릿과 레코드는 논리적 개념이며 InputSplit 인터페이스의 구현체로 표현됨
  2. 맵리듀스 프로그래밍에서는 InputSplit을 다루는 (입력 스플릿 생성 및 레코드로의 분할하는) InputFormat 인터페이스 구현체를 사용함
  3. 크기가 큰 스플릿을 우선으로 순차적으로 처리함으로써 잡 수행시간을 최소화하도록 함
  4. MultithreadedMapRunner
  1. MapRunnable의 다른 구현체
  2. mapred.map.multithreadedrunner.threads 속성의 개수만큼 동시에 매퍼 실행
  3. 각 레코드를 처리하는 데에 시간이 드는 매퍼에 대하여 적용하면 효과적임
  1. InputSplit
  1. long getLength()
  1. 바이트 길이 반환
  1. String[] getLocations()
  1. 호스트네임 문자열로 된 저장소 위치 반환
  1. InputFormat
  1. InputSplit[] getSplits(JobConf job, int numSplits)
  1. hint로서 원하는 맵태스크 개수 설정
  2. 입력 데이터 크기와 파일 블록 크기로 계산된 임의 개수 반환
  1. RecordReader<K,V> getRecordReader(InputSplit split, JobConf job, Reporter reporter)
  1. 레코드의 Iterator 반환
  2. MapRunner 구현에서 reader로부터 map맵퍼의 입력을 얻음
  3. while(reader.next(key, value) { mapper.map(key, value, output, reporter); }
  1. FileInputFormat
  1. 입력파일 경로 지정 구현 (파일 지정, 파일 패턴 지정)
  1. addInputPath(s)(..), setInputPaths(..)
  2. mapred.input.dir 속성
  1. 특정 입력파일 배제 필터 구현
  1. setInputPathFilter(..)
  2. 필터 미설정시 기본 필터로 시스템 숨김 파일 배제 처리
  3. mapred.input.path.filter.class 속성
  1. 입력파일 스플릿 생성 구현
  1. 일반적으로 HDFS 블록보타 큰 파일을 블록 크기의 스플릿으로 분할
  2. 파일 스플릿의 최소(기본 - 1)/최대(기본 - Long.MAX_VALUE) 바이트 속성 설정 가능
  3. 최소크기 < 블록크기 < 최대크기
  1. 스플릿의 레코드 분할에 대한 자식 클래스 구현 강제
  1. CombineFileInputFormat
  1. HDFS 블록보다 작은 파일들을 처리할 때 하둡의 성능을 보완함
  2. 노드와 랙의 위치를 고려하여 블록들을 스플릿으로 묶음
  3. 추상 클래스이므로 하위 클래스에서 getRecordReader(..) 구현 필요
  4. SequenceFile을 이용하여 작은 파일을 더 큰 파일로 병합하여 저장하는 것을 권고함
  1. 스플릿 방지 기법
  1. 최소 스플릿 크기를 Long.MAX_VALUE로 설정
  2. FileInputFormat하위 클래스의 하위 클래스를 생성하여 isSplitable() 메소드를 false가 반환되도록 구현
  1. 매퍼의 파일 정보
  1. 매퍼는 잡 환경 설정 객체의 속성으로부터 스플릿에 대한 정보를 획득 가능
  2. 파일 스플릿 속성
  1. map.input.file - 처리될 입력 파일 경로
  2. map.input.start - 시작 지점 바이트 오프셋
  3. map.input.length - 바이트 길이
  1. 전체 파일을 하나의 레코드로 처리하는 방법
  1. 285P 예제 소스코드 참조
  2. FileInputFormat 하위 클래스 구현
  1. isSplitable() 메소드 오버라이드하여 false 반환
  2. key → NullWritable, value → BytesWritable로 타입 결정
  1. RecordReader 구현
  1. next(key, value) 메소드 내에서 연 파일을 바이트 배열에 넣고, ByteWritable 인스턴스에 바이트 배열을 할당하도록 구현
  1. TextInputFormat
  1. 키 → LongWritable - 파일 내에서 라인 시작 지점의 바이트 오프셋 주소
  2. 값 → Text - 라인의 내용(개행문자 제외)
  1. FileInputFormat이 정의하는 논리적인 레코드가 HDFS 블록에 정확히 들어맞지 않는 경우, 두 블록에 걸쳐진 레코드까지 포함하여 하나의 스플릿으로 간주함
  2. KeyValueTextInputFormat
  1. 키, 구분자, 값이 명시된 텍스트 파일이 입력인 경우 사용
  1. NLineInputFormat
  1. 매퍼가 고정된 개수의 입력 라인을 받고자 하는 경우(스플릿에 포함될 라인 수를 고정하는 경우) 사용
  2. mapred.line.input.format.linespermap 속성 - 입력 라인수 설정
  3. 시뮬레이션과 같이 작은 양의 입력을 취하고 많은 연산을 수행한 결과물을 내는 응용 프로그램에 적합
  1. 태스크 타임아웃 발생 방지를 위해 상태나 증가된 카운터를 주기적으로 보고해야 함
  1. StreamXmlRecordReader
  1. XML문서 내의 시작, 종료 태그에 대한 정규표현식 패턴을 지정하여 레코드로 나눌 수 있음
  2. stream.recordrerader.class 속성 -  org.apache.hadoop.streamin.StreamXmlRecordReader로 설정
  3. 입력포맷 - StreamInputFormat
  1. 바이너리 입력
  1. SequenceFileInputFormat
  1. 시퀀스파일을 맵리듀스 입력으로 사용하는 경우 사용
  2. 파일경로가 디렉토리인 경우 MapFile을 읽는 것으로 간주하여 MapFile을 읽어들일 수도 있음
  1. SequenceFileAsTextInputFormat
  1. 시퀀스파일의 키와 값을 Text객체로 변환시키는 경우 사용
  2. 시퀀스파일을 Streaming을 위한 입력 데이터로 만드는 경우 사용
  1. SequenceFileAsBinaryInputFormat
  1. 시퀀스파일의 키와 값을 임의의 바이너리 객체로 변환시키는 경우 사용
  2. 키와 값은 BytesWritable 객체로 캡슐화됨
  1. MultipleInputs
  1. 서로 다른 포맷의 입력을 처리하여 동일한 맵 출력물을 생성하고자 하는 경우 사용
  2. FileInputFormat.addInputPath()를 오버라이드/오버로드한 메소드 제공
  1. DBInputFormat
  1. RDB에서 JDBC로 데이터를 읽는 입력 포맷
  2. 이 포맷에 대해서 sharding기능이 없으므로 너무 많은 매퍼를 실행해서 대상 DB에 과부하를 주지 않도록 해야 함
  3. MultipleInputs를 이용하여 HDFS 상의 더 큰 데이터셋과 조인할 작은 데이터셋을 올리는 데에 적합함
  4. DBOutputFormat으로 잡의 결과물을 DB에 전송함
  5. 대안으로 SQOOP을 고려할 수 있음
  6. TableInputFormat/TableOutputFormat - HBase용 입출력 모델
  1. 출력 포맷
  1. TextOuputFormat
  1. 레코드를 텍스트의 라인으로 기록
  2. toString() - 키, 값을 문자열로 변환
  1. 바이너리 출력
  1. SequenceFileOutputFormat
  1. 시퀀스파일로 출력
  2. 추가 맵리듀스 잡 존재시 유용함
  1. SequenceFileAsBinaryOutputFormat
  1. 바이너리 포맷으로 키, 값을 시퀀스파일 컨테이너로 출력
  1. MapFileOutputFormat
  1. MapFiles로 출력
  2. 리듀서에서 키를 정렬하여 MapFile의 키를 순서대로 추가해야 함
  1. MultipleOutputFormat / MulipleOutputs
  1. 리듀서 당 다수의 출력파일을 생성하는 경우 사용
  2. MultipleOutputs이 더 많은 기능을 가지며 MultipleOutputFormat은 출력 디렉토리 구조와 파일 이름을 제어할 때 유용함
  3. MultipleOutputFormat
  1. 파일과 디렉토리 이름에 대한 완벽한 제어 가능
  2. 하위 클래스 - MultipleTextOutputFormat, MultipleSequenceFileOutputFormat
  3. protected String generateFileNameForKeyValue(key, value, name) - 하위 클래스에서 재정의하여 사용함
  1. MultipleOutputs
  1. 다른 출력파일에서는 다른 타입의 키와 값 사용 가능
  2. 같은 잡에서 맵과 리듀스에 의해 사용
  3. 레코드 별 다중 출력파일 생성
  4. 어떤 OutputFormat도 사용 가능
  1. LazyOutputFormat
  1. 출력할 결과가 있을 경우에만 출력파일이 생성되도록 함
  2. jobconf.setOutputFormatClass(..)에 지정

댓글 없음:

댓글 쓰기