大数据 Shuffle 原理与实践 | 青训营笔记
这是我参与「第四届青训营 」笔记创作活动的的第6天,本篇笔记主要是关于第六次大数据课程《大数据 Shuffle 原理与实践》的课堂笔记
MapReduce
三个阶段:
- map:是在单机上针对一小段数据的计算过程
- shuffle:在map阶段的基础上,进行数据移动(整合各单机),为后续的reduce阶段做准备
- reduce:对移动后的数据进行处理,依然是单机上处理一小份数据、
Shuffle算子分类
Shuffle Dependency
- 创建会产生shuffle的RDD时,RDD会创建Shuffle Dependency来描述Shuffle相关的信息 Partitioner:用来将record映射到具体的partition的方法
Aggregator:
- 在map侧合并部分record的函数
- 接口
- createCombiner:只有一个value的时候初始化的方法
- mergeValue:合并一个value到Aggregator中
- mergeCombiners:合并两个Aggregator
Hash Shuffle
- 写数据:每个partition会映射到一个独立的文件 缺点:生成的文件太多了,同时打开的文件也会很多
- 写数据优化:每个partition会映射到一个文件片段 缺点:文件数量没有得到根本性的解决
Sort Shuffle
- 写数据:每个task生成一个包含所有partition数据的文件
- 读数据:每个reduce task分别获取所有map task生成的属于自己的片段
Shuffle过程的触发流程
在collect中会调用spark中SubmitJob,分析RDD的依赖关系同时创建Shuffle RDD的对象,同时向Shuffle manager注册自己。
Shuffle Handle的创建
Register Shuffle时做的最重要的事情是根据不同条件创建不同的shuffle Handle
ShuffleReader网络请求流程
Reader实现——ShuffleBlockFetchIterator
- 区分local和remote节省网络消耗
- 防止OOM(内存溢出)
- maxBytesInFlight
- 限制获取的数据范围大小
- maxReqsInFlight
- 限制请求的数量
- maxBlocksInFlightPerAddress
- 限制每个地址上获取block的数量
- maxReqSizeShuffleToMem
- 限制放到Mem里的最大请求数量
- maxAttemptsOnNettyOOM
- 控制OOM的次数
External Shuffle Service
为了解决Executor为了服务数据的fetch请求导致无法退出问题,我们在每个节点上部署一个External Shuffle Service,这样产生数据的Executor在不需要继续处理任务时,可以随意退出。
shuffle优化
- 避免shuffle ——使用broadcast替代join 使用Broadcast将一个数据量较小的RDD作为广播变量
- 使用可以map-side预聚合的算子
- Shuffle 倾斜优化
- 倾斜:数据在进行分类之后分布不均匀
- 倾斜影响:
- 作业运行时间变长
- Task O0M导致作业失败
Push Shuffle
背景: 以前的shuffle有一些问题:
- 数据存储在本地磁盘,没有备份
- IO 并发:大量 RPC 请求(M*R)
- IO 吞吐:随机读、写放大(3X)
- GC 频繁,影响 NodeManager
流程:
- Cloud Shuffle Service架构
- Zookeeper WorkerList [服务发现]
- CSS Worker [Partitions / Disk | Hdfs]
- Spark Driver [集成启动 CSS Master]
- CSS Master [Shuffle 规划 / 统计]
- CSS ShuffleClient [Write / Read]
- Spark Executor [Mapper + Reducer]
-
Cloud Shuffle Service 读写流程
-
Cloud Shuffle Service 支持AQE
- 在聚合文件时主动将文件切分为若干块,当触发AQE时,按照已经切分好的文件块进行拆分。