https://blog.csdn.net/lb812913059/article/details/79899644
https://blog.csdn.net/ASN_forever/article/details/81233547
https://blog.csdn.net/weixin_43823423/article/details/85986538
Map端shuffle
map端的shuffle包括环形内存缓冲区执行溢出写,partition,sort,combiner,生成溢出写文件,合并
Map端会处理输入数据并产生中间结果,这个中间结果会写到本地磁盘,而不是HDFS。并非简单地将它输出到磁盘,数据首先写到内存中的一个缓冲区,并做一些预排序
每个map任务都有一个环形内存缓冲区,用于存储任务的输出(默认大小100MB,mapreduce.task.io.sort.mb调整),被缓冲的K-V对记录已经被序列化,但没有排序。
一旦缓冲内容达到阈值(mapreduce.map.io.sort.spill.percent,默认0.80,或者80%),就会创建一个溢出写文件,同时开启一个后台线程把数据溢出写(spill)到本地磁盘中。溢出写过程按轮询方式将缓冲区中的内容写到mapreduce.cluster.local.dir属性指定的目录中
在写磁盘之前,线程首先根据数据最终要传递到的Reducer把数据划分成相应的分区(partition),输出key会经过Partitioner分组或者分桶选择不同的reduce。默认的情况下Partitioner会对map输出的key进行hash取模
然后在每个分区中,后台线程将数据按Key进行排序(排序方式为快速排序)。接着运行combiner在按key做本地聚合(如果设置了的话),可以减少传递给Reducer的数据量。
当溢出写文件生成数至少为3时(mapreduce.map.combine.minspills属性设置),combiner函数就会在缓存溢出文件合并的时候会调用
在写磁盘过程中,另外的20%内存可以继续写入数据,两种操作互不干扰,但如果在此期间缓冲区被填满,那么map就会阻塞写入内存的操作,让写入磁盘操作完成后再执行写入内存。
在每个Map任务完成前,溢出写文件被合并成一个索引文件和数据文件(多路归并排序)(Sort阶段)。一次最多合并多少由io.sort.factor控制,默认为10
溢出写文件归并完毕后,Map将删除所有的临时溢出写文件,并告知NodeManager任务已完成,只要其中一个MapTask完成,ReduceTask就开始复制它的输出(Copy阶段分区输出文件通过http的方式提供给reducer)
combiner
如果指定了Combiner,可能在两个地方被调用:
1.缓存溢出线程将缓存存放到磁盘时,就会调用(排序之后);
2.缓存溢出的文件数量超过mapreduce.map.combine.minspills(默认3)时,在缓存溢出文件合并的时候会调用
压缩
写磁盘时压缩map端的输出,因为这样会让写磁盘的速度更快,节约磁盘空间,并减少传给reducer的数据量。默认情况下,输出是不压缩的(将mapreduce.map.output.compress设置为true即可启动)