这是我参与「第四届青训营 」笔记创作活动的的第5天
- Spark介绍
- 基于内存计算的大数据开源计算集群环境
- 特点
- 统一引擎,支持多种分布式场景
- 多语言支持
- 可读写丰富数据源
- 丰富灵活的API算子
- SparkCore->RDD
- SparkSQL->DataFrame
- 支持K8S/YARN/Mesos资源调度
- 部署方式
- Spark Local Mode
- 本地测试/单进程多线程模式
- Spark Standalone Mode
- 需要启动Spark的Standalone集群的master/worker
- on YARN/K8S
- 依赖外部资源调度器(YARN/K8S)
- Spark Local Mode
- 部署方式
- SparkCore原理解析
- RDD(Resilient Distributed Dataset)
- 是一种对数据集形态的抽象,基于此抽象,使用者可以在集群中执行一系列计算,而不用将中间结果落盘。
- 五要素
- Partitions(分区集)
- 分区是每个RDD最小构成单元
- Compute(变换函数)
- 作用于分区上的变换函数,可以由几个父分区计算得到一个子分区
- Dependencies(依赖集)
- RDD之间存在父子依赖关系
- Partitioner(分区模式)
- 基于哈希切片/直接切分
- PreferredLocations(数据放置)
- 知道分区的存放位置可以进行计算优化
- Partitions(分区集)
- 如何创建RDD
- 内置RDD
- ShuffleRDD/HadoopRDD/JDBCRDD
- KafkaRDD/UnionRDD/MapPartitionsRDD
- 自定义RDD
class CustomRDD(...)extends RDD{}- 实现五要素对应的函数
- 内置RDD
- RDD算子
- Transform算子
- 生成一个新的RDD
- map/filter/flatMap/groupBy/reduceBy
- Action算子
- 触发Job提交
- collect/count/take/saveAsTextFile
- Transform算子
- RDD依赖
- 窄依赖
- 父RDD的每个partition至多对应一个子RDD分区
- NarrowDependency
- OneToOneDependency
- RangeDependency
- PruneDependency
- 宽依赖
- 父RDD的每个partition可能对应多个子RDD分区
- ShuffleDependency
- 窄依赖
- 调度器
- RDD.action->runJob()
- 根据ShuffleDependency切分stage,并按照依赖顺序调度stage,为每个stage生成并提交TaskSet到TaskScheduler
- 根据调度算法(FIFO/FAIR)对多个TaskSet进行调度,对于调度到的TaskSet,会将Task调度(locality)到相关Executor上执行,Executor SchedulerBackend提供
- 内存管理
- Executor内存主要有两类:Storage/Execution
- UnifiedMemoryManager统一管理Storage/Execution内存
- Storage/Execution内存使用动态调整,可以相互借用
- 当Storage空闲时,Execution可以借用Storage的内存使用
- 可以减少spill等操作,Execution使用的内存不能被Storage驱逐
- 当Execution空闲时,Storage可以借用Execution的内存使用
- 当Execution需要内存时,可以驱逐被Storage借用的内存,直到spark.memory.storageFraction边界
- 多任务间内存分配
- UnifiedMemoryManager统一管理多个并发Task的内存分配
- 每个Task获取的内存区间为
1/(a*N)~1/N(N为当前Executor中正在并发运行的Task数量)
- Shuffle机制
- map与reduce之间数据处理和重新分发的过程被称为Shuffle
- SortShuffleManager
- External Shuffle Service
- RDD(Resilient Distributed Dataset)
- SparkSQL原理解析
- Catalyst优化器*
- RBO
- RuleExecutor
- Batch->Once
- 只执行一次
- Batch->FixedPoint
- 重复执行,直到plan不在变化,或者执行达到固定次数(默认100次)
- Batch->Once
- RuleExecutor
- CBO
- RBO
- AQE(Adaptive Query Execution)
- partition合并
- 作业运行过程中,根据前面运行完的Stage的MapStatus中实际的partition大小信息,可以将多个相邻的较小的partition进行动态合并,由一个task读取进行处理
- 动态切换join策略
- AQE运行过程中动态获取准确join的leftchild/rightChild的实际大小,将SMJ转换为BHJ
- 处理join倾斜问题
- AQE根据MapStatus信息自动检测是否有倾斜,将大的partition拆分成多个task进行join
- partition合并
- Runtime Filter
- Bloom Runtime Filter
- Codegen
- Expression
- 将表达式中的大量虚函数调用压平到一个函数内部,类似手写代码
- WholeStageCodegen
- 算子之间大量虚函数调用,开销大,将同一个stage的多个算子压平到一个函数内部使用
- Expression
- Catalyst优化器*
- 业界挑战与实践
- Shuffle稳定性问题
- 在大规模作业下,开源ESS(ExternalShuffleService)的实现机制容易带来大量随机读导致的磁盘IOPS瓶颈、Fetch请求积压等问题,进而导致运算过程中经常会出现Stage重算甚至作业失败,继而引起资源使用的恶性循环,严重影响SLA
- SQL执行性能问题
- 参数推荐/作业诊断
- Shuffle稳定性问题