Reduce
- Copy
- Merge
- Reduce
Copy
走到这里,我们就进入到reduce了。
reduce有三个明确的阶段:copy,sort,reduce。
在初始化ShuffleConsumerPlugin
的时候,他需要创建一个MergeManager:
这个MergeManager就是用来做文件合并的。
接下来我们使用localFetcher
去拉取map的输出文件。
在此我们将获取file.out文件和file.out.index文件。
我们将所有的data读取到memory这个byte数组中。
此时copy就结束了。
Merge
我们进入merger.close()
并注意它的返回值是RawKeyValueIterator
,这里将封装所有数据。
在finalMerge
中,它经历了几次merge,我们看看最终的效果:
首先磁盘上有溢写的merge file。
最终返回的MergeQueue
是一个RawKeyValueIterator
,它里面有一个Object
数组存放着所有数据。
最后我们会将RawKeyValueIterator
传递下去跑reducer。
Reduce
首先我们要构建一个Reducer的上下文对象,将他作为参数扔到reducer.run
中。
这时候就会来到我们熟悉的自定义的reduce方法。
我们将跟踪context.nextKey()
方法,看他经历了哪些过程:
注意此时的key
和value
都是空的,而那个input
就是我们一直关注的RawKeyValueIterator
。
这里的buffer已经有了hadoop
这个词的位置和数据了。
跟踪key = keyDeserializer.deserialize(key);
最后我们读到了hadoop
并返回,注意到writable.readFields(dataIn)
的dataIn
就是之前的buffer对象。
这样我们就进到了自己的reduce方法。因为之前排过序(归并排序)了,所以同一个key的数据会一次性进入reduce方法。
写完后我们就会得到一个分区的结果:
然后再来一个ReduceTask处理第二个分区: