这是我参与【第四届青训营-大数据场】笔记创作活动的第7天
Spark中对shuffle的抽象-宽依赖、窄依赖
窄依赖:
- 父 RDD 的每个分片至多被子
- RDD 中的一个分片所依赖
宽依赖:
- 父 RDD 中的分片可能被子
- RDD 中的多个分片所依赖
Shuffle Dependency 构造
- A single key-value pair RDD, i.e. RDD[Product2[K, V]]. Partitioner (available as partitioner property) Serializer,
- Optional key ordering (of Scala’s scala.math.Ordering type) Optional Aggregator,
- mapSideCombine flag which is disabled (i.e. false) by default.
Shuffle Dependency构造-Aggregator
- createCombiner:只有一个value 的时候初始化的方法
- mergeValue: 合并一个 value 到 Aggregator 中
- mergeCombiners:合并两个 Aggregator
Shuffle 实现的发展历程
- Spark 0.8 及以前 Hash Based Shuffle
- Spark 0.8.1 为 Hash Based Shuffle引入File Consolidation机制.Spark 0.9 引入 ExternalAppendOnlyMap
- Spark 1.1 引入 Sort Based Shuffle,但默认仍为 Hash Based Shuffle Spark 1.2 默认的 Shuffle 方式改为 Sort Based Shuffle Spark 1.4 引入 Tungsten-Sort Based Shuffle
- .Spark 1.6 Tungsten-Sort Based Shuffle 并入 Sort Based Shuffle. Spark 2.0 Hash Based Shuffle 退出历史舞台
-
使用基于netty的网络通信框架
-
位置信息记录在MapOutputTracker中
-
主要会发送两种类型的请求
-
OpenBlocks请求
-
。Chunk请求或Stream请求
-
区分local和remote节省网络消耗
-
防止OOM
-
maxBytesInFlight
-
maxReqslnFlight
-
maxBlocksInFlightPerAddress
-
maxReqSizeShuffleToMem
-
maxAttemptsOnNettyOOM
Reader 实现-ShuffleBlockFetchlterator
- ESS作为一个存在于每个节点上的agent
- 为所有Shuffle Reader提供服务,从而
- 优化了Spark作业的资源利用率,
- MapTask在运行结束后可以正常退出
Shuffle 优化使用的技术: Netty Zero Copy
-
可堆外内存,避免 JVM 堆内存到堆外内存的数据拷贝。
-
VCompositeByteBuf、Unpooled.wrappedBuffer、ByteBuf.slice ,可以合并、包装、切分数组,避 免发生内存拷贝
-
Netty 使用 FileRegion 实现文件传输,FileRegion 底层封装了 FileChannel#transferTo()方法,可以将文件缓冲区的数据直接传输到目标 Channel,避免内核缓冲区和用户态缓冲区之间的数据拷贝
-
AQE 根据 shuffle 文件统计数据自动检测倾斜数据,将那些倾斜的分区打散成小的子分区,然后各自进行join。
为什么需要 Push Shuffle
Avg 1O size太小,造成了大量的随机1O,严重影响磁盘的吞吐 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
Magnet可靠性
- 如果Map task输出的Block没有成功Push到magnet上,并且反复重试仍然失败,则reduce task直接从ESS上拉取原始block数据
- 如果magnet上的block因为重复或者冲突等原因,没有正常完成merge的过程,则reduce
- task直接拉取未完成merge的block
- 如果reduce拉取已经merge好的block失败,则会直接拉取merge前的原始block本质上,magnet中维护了两份shuffle数据的副本