Reduce

  • Copy
  • Merge
  • Reduce


Copy

mapreduce文件合并和去重_mapreduce文件合并和去重

走到这里,我们就进入到reduce了。

mapreduce文件合并和去重_reduce_02

reduce有三个明确的阶段:copy,sort,reduce。

在初始化ShuffleConsumerPlugin的时候,他需要创建一个MergeManager:

mapreduce文件合并和去重_源码_03

mapreduce文件合并和去重_源码_04

这个MergeManager就是用来做文件合并的。

mapreduce文件合并和去重_源码_05

接下来我们使用localFetcher去拉取map的输出文件。

mapreduce文件合并和去重_hadoop_06

在此我们将获取file.out文件和file.out.index文件。

mapreduce文件合并和去重_mapreduce_07

我们将所有的data读取到memory这个byte数组中。

mapreduce文件合并和去重_mapreduce文件合并和去重_08

此时copy就结束了。

Merge

mapreduce文件合并和去重_hadoop_09

我们进入merger.close()并注意它的返回值是RawKeyValueIterator,这里将封装所有数据。

mapreduce文件合并和去重_mapreduce文件合并和去重_10

finalMerge中,它经历了几次merge,我们看看最终的效果:

mapreduce文件合并和去重_mapreduce_11

首先磁盘上有溢写的merge file。

mapreduce文件合并和去重_hadoop_12

最终返回的MergeQueue是一个RawKeyValueIterator,它里面有一个Object数组存放着所有数据。

mapreduce文件合并和去重_hadoop_13


最后我们会将RawKeyValueIterator传递下去跑reducer。

Reduce

mapreduce文件合并和去重_源码_14

首先我们要构建一个Reducer的上下文对象,将他作为参数扔到reducer.run中。

这时候就会来到我们熟悉的自定义的reduce方法。

mapreduce文件合并和去重_mapreduce文件合并和去重_15

我们将跟踪context.nextKey()方法,看他经历了哪些过程:

mapreduce文件合并和去重_源码_16

mapreduce文件合并和去重_reduce_17

注意此时的keyvalue都是空的,而那个input就是我们一直关注的RawKeyValueIterator

mapreduce文件合并和去重_mapreduce文件合并和去重_18

这里的buffer已经有了hadoop这个词的位置和数据了。

跟踪key = keyDeserializer.deserialize(key);

mapreduce文件合并和去重_reduce_19

最后我们读到了hadoop并返回,注意到writable.readFields(dataIn)dataIn就是之前的buffer对象。

mapreduce文件合并和去重_mapreduce_20

这样我们就进到了自己的reduce方法。因为之前排过序(归并排序)了,所以同一个key的数据会一次性进入reduce方法。

写完后我们就会得到一个分区的结果:

mapreduce文件合并和去重_mapreduce文件合并和去重_21

然后再来一个ReduceTask处理第二个分区:

mapreduce文件合并和去重_mapreduce_22