Spark:
1.Spark中的shuffle有哪些?
1.1.最早的Hash Based Shuffle(2.0以上被弃用)
每个Mapper对每一个Reducer都会创建相应的bucket,bucket数量为
Mapper个数×Reducer个数。缺点是会产生太多小文件,后面将一个core上的
多个Mapper的输出合并到同一个文件,bucket数量变为core的个数。
1.1.* 代替Hash based Sort的是BypassMergeShuffleWriter
实现方式基本一致,不同之处在于Mapper端的所有输出文件会被汇总成一个文件,
并生成一个索引文件,为了索引到各分区起始地址,可随机索引到各分区。
注意:该方式不宜有太多分区,会并发打开所有分区的临时文件。
实现方式:将Mapper输出的数据通过对Key进行Hash(或自定义分区器)分到
不同分区的临时文件上,然后再将这些文件再copy到一个文件,没有用到
内存的Buffer。
1.2.SortShuffleWriter
Map端按照Partition id以及Key对记录进行排序。
具体实现:
1.使用PartitionedAppendOnlyMap或PartitionedPairBuffer
(HashTable实现),在内存中排序,
排序的键值对里的Key就是(partition id,hash(key) )这样一个元组
2.若内存超出,则将数据溢写到文件中,是按照 partition id 和 key 有序的。
3.需要全局有序时,则将之前所有出输出文件和当前内存中的数据全局排序。
排序算法:假如共有100亿数据,但内存一次只能加载1亿条,那么能分10次
分别排序输出到10个文件中,局部有序(从小到大)。利用小顶堆,
将10个文件中各取前n条作为堆元素,即一个堆元素里有多条数据,
做成小顶堆然后pop出堆顶元素的第一个值(肯定是最小的),
再按照每个堆元素的第一个元素维护小顶堆,不断pop到一个文件。
若一个堆元素里的n条数据都pop出去了,则再读磁盘文件中得n条补上。
4.最后得到一个partition id全局有序、Key局部有序的的汇总文件,以及一个索引文件。
3.UnSafeShuffleWriter
1.维护着一个ShuffleExternalSorter,用来做外部排序。
外部排序就是部分数据排序存到磁盘,在归并全局排序。
2.只根据partition id排序
3.具体实现:不断地往这个Sorter插入数据,内存满了就溢写到文件,在归并。
4.最后得到partition id全局有序的大文件。