这是我参与「第四届青训营 」笔记创作活动的的第6天
一、Shuffle概述
Map阶段
Map阶段,是在单机上进行的针对一小块数据的计算过程\
Shuffle阶段
Shuffle阶段,在map阶段的基础上,进行数据移动,为后续的reduce阶段做准备。
Reduce过程
reduce阶段,对移动后的数据进行处理,依然是在单机上处理一小份数据\
总结
在大数据场景下,数据shufle表示了不同分区数据交换的过程,不同的shuffle策略性能差异较大。 目前在各个引擎中shuffle都是优化的重点,在spark框架中,shuffle 是支撑spark进行大规模复杂 数据处理的基石。
二、Shuffle算子
Shuffle算子应用
- Spark源码中RDD的单元测试
- Spark源码中PairRDDFunctions的单元测试
Spark中对shuffle的抽象-宽依赖、窄依赖
- 窄依赖:父RDD的每个分片至多被子RDD中的一个分片所依赖
- 宽依赖:父RDD中的分片可能被子RDD中的多个分片所依赖
Shuffle Dependency构造- Partitioner
两个接口
- numberPartitions
- getPartition
经典实现
- HashPartitioner
Shuffle Dependency构造- Aggregator
- createCombiner:只有一个value 的时候初始化的方法
- mergeValue:合并一个value到Aggregator中
- mergeCombiners:合并两个Aggregator
三、Shuffle过程
Hash Shuffle -写数据
每个partition会映射到一个独立的文件
Hash Shuffle -写数据优化
每个partition会映射到一个文件片段
Sort shuffle :写数据
每个task生成个包含所有 partiton数据的文件
Shuffle -读数据
每个reduce task分别获取所有map task生成的属于自己的片段
Writer实现- BypassMergeShuffleWriter
- 不需要排序,节省时间
- 写操作的时候会打开大量文件
- 类似于Hash Shuffle
Writer实现- UnsafeShuffleWriter
- 使用类似内存页储存序列化数据
- 数据写入后不再反序列化
Writer实现- UnsafeShuffleWriter
- 只根据partition排序Long Array
- 数据不移动
Writer实现- SortShuffleW riter
- 支持combine
- 需要combine时,使用PartitionedAppendOnlyMap, 本质是个HashTable
- 不需要combine时PartitionedPairBuffer本质是个array
Reader实现-网络时序图
- 使用基于netty的网络通信框架
- 位置信息记录在MapOutputTracker中
- 主要会发送两种类型的请求
- OpenBlocks请求
- Chunk请求或Stream请求
Reader实现- ShuffleBlockFetchlterator
- 区分local和remote节省网络消耗
- 防止OOM
- maxByteslnFlight
- maxReqslnFlight
- maxBlocksInFlightPerAddress
- maxReqSizeShuffle ToMem
- maxAttemptsOnNettyOOM
Read实现一External Shuffle Service
ESS作为一个存在于每个节点上的agent为所有Shuffle Reader提供服务,从而优化了Spark作业的资源利用率,MapTask在运行结束后可以正常退出.
四、Push Shuffle
为什么需要Push Shuffle ?
- Avg I0 size太小,造成了大量的随机IO,严重影响磁盘的吞吐
- M * R次读请求,造成大量的网络连接,影响稳定性
Magnet实现原理
- Spark driver组件,协调整体的shuffle操作
- map任务的shuffle writer过程完成后,增加了-个额外的操作push. merge,将数据复制一份推到远程shuffle服务上
- magnet shuffle service是一个强化版的ESS。将隶属于同一个shuffle partition的block,会在远程传输到magnet后被merge到一个文件中
- reduce任务从magnet shuffle service接收合并好的shuffle数据
- bitmap:存储已merge的mapper id,防止重复merge
- position offset:如果本次block没有正常merge,可以恢复到上一个block的位置
- currentMapld:标识当前正在append的block,保证不同mapper 的block能依次append