这是我参与「第四届青训营 」笔记创作活动的第5天
1. shuffle概述
2. Shuffle算子
3. Shuffle过程
4. Push shuffle(各社区实现方案和字节方案)
1. shuffle概述
1.1 Mapreduce
开源实现的map-reduce中,存在 map、shuffle、reduce
1.2 shuffle对性能影响重大
-M*R次网络连接
-大量数据移动
-数据丢失风险
-可能存在大量排序操作
-大量数据序列化、反序列化
-数据压缩
2 shuffle算子
四类会产生shuffle的算子
Repartition:重新改编分区
Bykey:key聚合到一起
Join:把本身不是在一起的数据按照某条件放一起进行计算
Distinct:可以理解为一种特殊的bykey
2.1 Spark中对shuffle的抽象 - 宽依赖、窄依赖(RDD之间有依赖关系)
窄依赖:父RDD的每个分片至多被子RDD中的一个分片所依赖
宽依赖:父RDD中的分片可能被子RDD中的分片所依赖
创建会产生shuffle的RDD时,RDD会创建Shuffle Dependency来描述Shuffle相关的信息
Shuffledependency由两个RDD创建:CoGroupedRDD、ShuffleedRDD;
而CoGroupedRDD、ShuffleedRDD由:Cogroup、combinebykeywithclasstag等操作创建。
2.1.1 shuffle dependency构造函数
Partitioner
负责把key映射成数字,此数字代表某一具体分区。(将record映射到具体的partition的方法)
两个接口:numberPartitions、getPartition。经典实现:Hashpartitioner。
说明有多少个分区,并说明key在那个分区
Aggregator
在map侧合并部分record的函数
接口:
CreateCombiner:只有一个value的时候初始化的方法
MergeValue:合并到一个value到Aggregator中
Mergecombiners:合并两个Aggregator
3 shuffle过程
3.1 Shuffle变迁过程
-HashShuffle 写数据
优点:不需要排序
缺点:打开,创建的文件过多
每个partition会映射到一个独立的文件
-HashShuffle 写数据优化
每个partition会映射到一个文件片段
-SortShuffle 写数据
优点:打开的文件少、支持map-side combine
缺点:需要排序
每个task生成一个包含所有partition数据的文件
-TungstenSortShuffle
优点:更快的排序效率,更高的内存利用效率
缺点:不支持map-side combine
3.2 Shuffle-读数据
每个reduce task分别获取所有map task生成的属于自己的片段
3.3 Shuffle过程的触发流程
Collect action→submit job→get dependencies→register shuffle
3.4 Register Shuffle
-由action算子触发DAG Scheduler进行shuffle register
-Shuffle Register会根据不同的条件决定注册不同的ShuffleHandle
3.5 Shuffle Handle与Shuffle Writer的对应关系
BypassMergeSortShuffleWriter:HashShuffle
UnsafeShuffleWriter:TunstonShuffle
SortSHuffleWriter:SortShuffle
3.6 Writer实现
3.6.1 BypassMergeSortShuffleWriter
-不需要排序
-写操作的时候会打开大量文件
-类似Hash Shuffle
3.6.2 UnsafeShuffleWriter
-使用类似内存页储存序列化数据
-数据写入后不再反序列化
3.6.3 Writer实现-SortShuffleWriter
-支持combine
-需要combine时,使用partitionedAppendOnlyMap,本质是个HashTable
-不需要combine时PartitionedPairBuffer本质是个array
3.7 Reader实现 - 网络时序图
-使用基于netty的网络通信框架
-位置信息记录在MapOutputTracker中
-主要会发送两种类型的请求:OpenBlocks请求、Chunk请求或Stream请求
使用netty作为网络框架提供网络服务,并接受reducetask的fetch请求
首先发起openBlocks请求获得streamID,然后再处理stream或则chunk请求
3.7.1 ShuffleBlockFetchIterator
-区分local和remote节省网络消耗
-防止OOM
-maxBytesInFlight
-maxReqsInFlight
-maxBlocksInFlightPerAddress
-maxReqSizeShuffleToMem
-maxAttemptsOnNettyOOM
3.7.2 External Shuffle Service
ESS作为存在于每个节点上的agent为所有Shuffle Reader提供服务,从而优化了Spark作业的资源利用率,Maptask在运行结束后可以正常退出。(解决了Executor为了服务数据的fetch请求导致无法退出问题)
3.8 Shuffle优化
-避免shuffle——使用broadcast替代join
-使用可以map-side预聚合的算子
-shuffle参数优化
-shuffle倾斜优化
(1)提高并行度(足够简单,但不根治)
(2)AQE
4 Push Shuffle
为什么需要Push Shuffle?
-Avg IO size太小,造成大量随机IO
-M*R次读请求,造成大量的网络连接,影响稳定性
LinkedIn:magnet
Bytedance:CSS
Cloud Shuffle Service思想:Shuffle失败不可怕,重试即可,用极小的代价去换取远程Shuffle中的写入速度问题、高可用兜底问题。