目录
一、什么是shuffle,为什么要用shuffle?
二、shuffle工作流程
三、流程图详细讲解:以wordcount作为案例
一、什么是shuffle,为什么要用shuffle?
数据从Map阶段传递给Reduce阶段的过程就叫Shuffle,Shuffle机制是整个MapReduce框架中最核心的部分。
Mapreduce要确保每个reducer的输入都是按键排序的。
二、shuffle工作流程
1、Collect阶段:将MapTask的结果输出到默认大小为100M的环形缓冲区,保存key/value序列化数据,Partition分区信息等。
2、Spill 阶段:当内存中的数据达到阀值(默认80%)的时候,会将数据写入本地磁盘,在将数据写入磁盘之前需要对数据进行一次排序的操作,如果配置了combiner,还会将有相同分区号和key的数据进行排序。
3、.Merge 阶段:把所有溢出的临时文件进行一次合并操作,以确保一个MapTask最终只产生一个中间数据文件。
4、Copy阶段: ReduceTask启动Fetcher线程到已经完成MapTask的节点上复制一份属于自己的数据,这些数据默认会保存在内存的缓冲区中,当内存的缓冲区达到一定的阀值的时候,就会将数据写到磁盘之上。
5、Merge阶段:在ReduceTask远程复制数据(http)的同时,会在后台开启两个线程(一个是内存到磁盘的合并,一个是磁盘到磁盘的合并)对内存到本地的数据文件进行合并操作。
6、Sort阶段:在对数据进行合并的同时,会进行排序操作,由于MapTask 阶段已经对数据进行了局部的排序,ReduceTask只需保证Copy的数据的最终整体有效性即可
简而言之:
Maptask会不断收集我们的map()方法输出的kv对,放到内存缓冲区(默认100M)中,当缓冲区达到饱和的时候就会溢出到磁盘中,如果map的输出结果很多,则会有多个溢出文件,多个溢出文件会被合并成一个大的溢出文件,在文件溢出、合并的过程中,都要调用partitoner进行分组和针对key进行排序(默认是按照Key的hash值对reduceTasks个数取模),之后reducetask根据自己的分区号,去各个maptask机器上取相应的结果分区数据,reducetask会将这些文件再进行合并(归并排序)。
三、流程图详细讲解:以wordcount作为案例
No.1:job.split文件是切片信息。
FileInputFormat切片:在MapReduce的执行过程当中,默认的数据分片大小为100M,但是这个大小可能会随着hdfs中block大小的设置而发生变 化,具体的切分规则如下:
max.split(100M)
min.split(10M)
block(128M)==>大小可以自定义
max(min.split,min(max.split,block))
根据上述规则进行计算的话,上例上的分片大小为100M。1.0 hadoop最后切片是64M.
No.2:LineRecordReader中next()方法会反复调用,读取数据,以偏移量(每一行的起始位置)、数据作为key、value发送给mapper
No.3:map()方法进行切分split,将单词作为key,个数 1 作为value发送出去
No.4:mappr发出去的数据会被MapOutCollector收集保存到内存的一个环形缓冲区
No.5:环形缓冲区数据达到阈值的时候,为了能让后面的数据进来,之前的数据会溢出到本地磁盘
No.6:在保存到本地文件之前,partition会对kv数据进行分区,默认是根据key的hashCode对reduceTasks个数取模得到的,相同的key会一个分区。
如果想改变分区规则,需要我们自定义一个类继承Partitioner,重写getPartition()方法,之前写过省份根据电话号分区的案例。
No.7:如果溢出到磁盘上文件达到一定数量,则会合并成一个更大文件
No.8:所有的maptask任务完成后,会通过http发送给reducer
No.9:reducetask根据自己的分区号,去各个maptask机器上取相应的结果分区数据。同一台机器会把不同maptask的结果文件再进行合并(归并排序)成大文件。
No.10:合并之后,shuffle过程也就结束了。reduce阶段会进行合并等操作。这里会有一个GroupingComparator分组器,会根据自己需求将指定数据按照组的形式存放在不同文件中,之前写过根据不同user求消费TopN的案例。
No.11:保存在hdfs中。
总体流程图: