MapReduce 2
MapReduce는 일종의 함수형 프로그래밍이다. map, reduce라는 합쳐진 용어로, 두 함수의 조합을 통해서 분산/병렬 시스템을 운용을 지원한다.
데이터 형태는 <Key , Value>형태로 저장이 되는데 여기서 키는 key는 라인이 시작되는 byte offset이며, value는 라인자체의 내용이다. 일반적으로 key는 관련이 없는 것으로 간주한다.
map(key, value) -> [(key,value),(key,value),(key,value)]
ex)
i am a
boy you
are a girl
==>
input : <1, "i am a"><2, "boy you"><3,"are a girl">
output : <i:1><am:1><a:2> ...<girl:1> (<key value>의 리스트형태)
맵 함수의 입력으로 키(k1), 값(v1)이 전달 되면, 맵 함수는 전달된 키-값을 이용해 사용자의 로직을 처리 (이미 구현된 map이 있지만, 사용자가 구현도 가능함.) 한 후 출력으로 새로운 키(k2)와 값(v2)의 리스트형태로 출력 한다. 이 때 키-값이 그대로 출력될 수 있으며, 출력 데이터의 갯수는 0 또는 1개 이상 일 수 있다.
맵 함수가 반복적으로 수행 되면 여러 개의 출력 데이터가 생성 되고, 이 출력 데이터를 키로 정렬하면 각 키에 여러 개의 데이터가 존재한다. 이 키(k2)와 값 목록(list(v2))이 리듀스 함수로 입력 된다. 리듀스 함수는 키-값 목록을 파라미터로 받아 사용자의 로직을 처리한 후 여러 개의 값을 출력 한다.
위 그림은 word Counter에 대한 예제이다.
① 맵리듀스 프레임워크는 입력 파일의 값을 라인 단위로 맵 함수에 전달. (key : 해당 라인의 번호, value : 해당 라인의 내용)
② 맵 함수는 공백을 기준으로 문자를 분리 한 후, 단어의 개수인 1을 출력
③ 맵 함수를 거쳐서 임시 결과가 출력
④ 출력결과를 키로 정렬 한 후, 각 값을 나열해 목록을 생성
⑤ 이렇게 정렬/병합 된 값(컴바인된 값)이 리듀스 함수로 전달
⑥ 리듀스 함수에서는 키에 단어가 전달되고, 값에 글자수 목록이 전달
⑦ 리듀스 함수는 값으로 글자수 목록에 반복을 수행 하면서, 합을 계산해 단어와 합을 출력
위의 예제를 수행 하기 위한 map 함수 와 reduce 함수이다. 참고하기 바란다.
map 함수
public class WordCountMapper extends Mapper<LongWritable, Text, Text, IntWritable>{ private final static IntWritable one = new IntWritable(1);
public void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException { StringTokenizer itr = new StringTokenizer(value.toString()); while (itr.hasMoreTokens()) { context.write(new Text(itr.nextToken()), one); } } } |
reduce 함수
public class WordCountReducer 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); } } |