大数据Shuffle原理| 青训营笔记

117 阅读3分钟

这是我参与「第四届青训营 」笔记创作活动的第5天

 

1. shuffle概述

2. Shuffle算子

3. Shuffle过程

4. Push shuffle(各社区实现方案和字节方案)

   

1. shuffle概述

1.1  Mapreduce

开源实现的map-reduce中,存在 map、shuffle、reduce

map-shuffle-reduce.png  

1.2 shuffle对性能影响重大

-M*R次网络连接

-大量数据移动

-数据丢失风险

-可能存在大量排序操作

-大量数据序列化、反序列化

-数据压缩

 

 

2  shuffle算子

四类会产生shuffle的算子

四类产生shuffle的算子.png

Repartition:重新改编分区

Bykey:key聚合到一起

Join:把本身不是在一起的数据按照某条件放一起进行计算

Distinct:可以理解为一种特殊的bykey

 

 

2.1  Spark中对shuffle的抽象 - 宽依赖、窄依赖(RDD之间有依赖关系)

窄依赖:父RDD的每个分片至多被子RDD中的一个分片所依赖

宽依赖:父RDD中的分片可能被子RDD中的分片所依赖

RDD之间的依赖.png

创建会产生shuffle的RDD时,RDD会创建Shuffle Dependency来描述Shuffle相关的信息

算子依赖关系.png

Shuffledependency由两个RDD创建:CoGroupedRDD、ShuffleedRDD;

而CoGroupedRDD、ShuffleedRDD由:Cogroup、combinebykeywithclasstag等操作创建。

 

2.1.1 shuffle dependency构造函数

shuffle dependency构造函数.png

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写数据.png  

-HashShuffle 写数据优化

每个partition会映射到一个文件片段

hashshuffle写数据优化.png

-SortShuffle 写数据

优点:打开的文件少、支持map-side combine

缺点:需要排序

每个task生成一个包含所有partition数据的文件

sortshuffle写数据.png  

-TungstenSortShuffle

优点:更快的排序效率,更高的内存利用效率

缺点:不支持map-side combine

 

 

3.2 Shuffle-读数据

每个reduce task分别获取所有map task生成的属于自己的片段

shuffle读数据.png  

 

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的对应关系

shufflehandle和shufflewriter.png

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请求

网络时序.png

使用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

image (2).png

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中的写入速度问题、高可用兜底问题。