这是我参与「第四届青训营 」笔记创作活动的第6天
Shuffle
MapReduce是最早由Google提出的一种编程模型,适用于TB级大数据计算。
开源实现的MapReduce存在3个阶段:Map->Shuffle->Reduce
- Map:在单机上针对一小块数据进行计算
- Shuffle:针对Map的结果进行块间的数据移动
- Reduce:单机上处理一小块移动过后的数据
Shuffle是开销最大的操作,需要对大量数据进行移动和排序,存在数据丢失的风险,因此对Shuffle的优化是性能优化的重点。
Shuffle算子
Shuffle算子分类:
repartition:coalesce、repartitionByKey:groupByKey、reduceByKey、aggregateByKey、combineByKey、sortByKey、sortByjoin:cogroup、join、leftOuterJoin、intersection、subtract、subtractByKeyDistinct:distinct
作业的拓扑结构中存在宽依赖和窄依赖:
- 窄依赖:父RDD的每个分片最多被子RDD的一个分片所依赖
- 宽依赖:父RDD的每个分片可能被子RDD的多个分片所依赖
Scheduler以宽依赖为边界划分stage,因此两个stage之间必有shuffle。
Shuffle过程
Shuffle技术演进
- Hash Shuffle V1
- 不进行排序
- 每个partition映射到一个独立文件,会生成大量文件
- Hash Shuffle V2
- 在V1的基础上将每个partition映射到一个文件片段,减少了文件数量
- Sort Shuffle
- 每个Task将所有结果写入一个文件
- 过程中会对记录进行排序,性能上有所损失
- 生成索引文件记录每个partition的大小和偏移量
Shuffle Writer
BypassMergeShuffleWriter
- 不需要排序,节省时间
- 写操作时会打开大量文件
- 类似于Hash Shuffle
UnsafeShuffleWriter
- 使用类似内存页储存序列化数据
- 数据写入后不再反序列化
SortShuffleWriter
- 支持combine
- 需要combine时,使用PartitionedAppendOnlyMap,本质是个HashTable
- 不需要combine时PartitionedPairBuffer本质是个array
Shuffle Reader
网络时序图
- 基于netty的网络通信框架
- 位置信息记录在MapOutputTracker中
- 主要发送OpenBlocks请求和Chunk或Stream请求
ShuffleBlockFetchIterator
- 区分local和remote节省网络资源
- 防止OOM
External Shuffle Service
- ESS作为一个存在于每个节点上的agent,为所有Shuffle Reader提供服务,从而优化了Spark作业的资源利用率,MapTask在运行结束后可以正常退出