shuffle概述:前一个stage 的 ShuffleMapTask 进行 shuffle write, 把数据存储在 blockManager 上面, 并
且把数据位置元信息上报到 driver 的 mapOutTrack 组件中, 下一个 stage 根据数据位置元信息,
进行 shuffle read, 拉取上个stage 的输出数据。
发展史
Shuffle产生的临时文件的数量的变化一次为:
Basic Hash Shuffle: M*R;
Consalidate方式的Hash Shuffle: C*R;
Sort-based Shuffle: 2*M;
-
Hash Based Shuffle
每个task根据reduce数量将数据进行hash,算出他们的partition,然后放入对应的内存缓冲区Bukket,每个Bukket就对应着一个文件。缺点是小文件太多,M*R个,不利于磁盘的连续读写。
-
Hash 加入Consolidate机制
对于同一Core的task他们的partition落地于同一文件。它降低了文件的数量,但是如果R过多依然不行。
-
Sort Based Shuffle
每个Task只会输出两个文件,分别是数据文件于索引文件,索引文件记录着不同partition的数据在data文件中的偏移。《存疑:这样做文件是少了,可是中间却涉及到了大量的小文件,依然会有很多磁盘的 随机读写啊》
实现细节:先排序,溢写小文件,再归并
SortShuffleWriter 中的处理步骤就是
1. 使用 PartitionedAppendOnlyMap 或者 PartitionedPairBuffer 在内存中进行排序, 排序的 K 是(partitionId, hash(key)) 这样一个元组。
2. 如果超过内存 limit, 我 spill 到一个文件中,这个文件中元素也是有序的,首先是按照 partitionId的排序,如果 partitionId 相同, 再根据 hash(key)进行比较排序
3. 如果需要输出全局有序的文件的时候,就需要对之前所有的输出文件 和 当前内存中的数据结构中的数据进行 merge sort, 进行全局排序
SortShuffleWriter 中使用 ExternalSorter 来对内存中的数据进行排序,ExternalSorter内部维护了两个集
合PartitionedAppendOnlyMap、PartitionedPairBuffer, 两者都是使用了 hash table 数据结构, 如果需
要进行 aggregation, 就使用 PartitionedAppendOnlyMap(支持 lookup 某个Key,如果之前存储过相同
key的K-V 元素,就需要进行 aggregation,然后再存入aggregation后的 K-V), 否则使用
PartitionedPairBuffer(只进行添K-V 元素)