Shuffle是什么?
MapReduce主要包括map和reduce过程。顾名思义,map是映射,即格式化输入字符串并过滤。reduce是减小,主要对日志进行一些聚合等数据统计操作。Shuffle处于map和reduce之间。
Shuffle本义洗牌、混洗,即将一组一定规则的数据转换为一组无规则的数据,越随机越好。而此处的Shuffle则像上述过程的逆过程,需要将数据按一定规则排序。
Shuffle过程
shuffle位于map和reduce之间,将map的输出处理后作为reduce的输入,MapReduce的实现过程如下
![MapReduce执行过程](https://img-blog.csdn.net/20171115201009583?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvc2t5X2ZseWluZzE=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
其中Shuffle包括中间的copy和sort部分,其具体流程如下
![Shuffle执行过程](https://img-blog.csdn.net/20171115201527690?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvc2t5X2ZseWluZzE=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
1. Collect
每一个map的每一条输出都将顺序写入一个环形结构的内存中,使用KV键值对的方式,采用环形结构的原因是因为其内存利用率高。同时给每一条数据都存储了一个索引,用于后面的排序等操作。
2. Sort
根据reduce个数和分区算法,计算出每一条数据的最终发送到的reduce节点编号partition值。使用partition和key值排序,最终相同的partition将会存储在一起,同时每一个partition内部有序。这里移动的也是索引而不是真实数据。
3. Spill
当环形结构中的内存使用了N%时,会将数据溢写到本地磁盘。创建一个类似“spill12.out”的文件,根据索引挨个partition的把数据突出到这个文件中,一个partition完成后继续下一个partition,直到将所有partition遍历完成。一个partition在文件中也称为一个段(segment)。
再创建一个类似“spill12.out.index”的文件,存储segment的索引,包括segment的起始位置,字符串长度和压缩后长度,这样利用索引就能够找到每一个segment的位置了。索引文件和数据文件的对应关系如下图所示
![Spill过程](https://img-blog.csdn.net/20171115210201053?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvc2t5X2ZseWluZzE=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
4. Merge
一个map都会输出一个或多个文件,最后会对这些小文件进行merge操作。
首先获取所有的数据文件目录列表和索引文件目录列表,然后挨个读取所有一个partition的所有segment索引,并输出到类似“file.out”的文件中,最终的结果就是一个map输出到一个文件中,并且每一个parition的数据连续存储,partition内部有序。
“file.out”的索引文件存储在index文件中
![merge过程](https://img-blog.csdn.net/20171115211045498?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvc2t5X2ZseWluZzE=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
map端的Shuffle过程到此就结束了,接下来是reduce的Shuffle过程。
5. Copy
使用http接口的方式,reduce将属于自己的segment下载到本地。一个reduce将会从多个map的输出中获取segment,所以需要进行下一步的merge操作
6. Merge sort
因为每一个segment都是有序的,所以使用归并排序的方式,在合并的同时进行sort,最后获得一个作为reduce输入的文件。