Spark原理与实践 | 青训营笔记
这是我参与「第四届青训营 」笔记创作活动的第5天
今天学习了课程《Spark原理与实践》,学习的内容主要分为以下几个部分:
- 大数据处理引擎Spark介绍
- SparkCore原理解析
- SparkSQL原理解析
- 业界挑战与实践
一、大数据处理引擎Spark介绍
1.1 开源大数据处理引擎
大数据处理引擎分为批式计算引擎、流式计算引擎、OLAP计算引擎。
- 批式计算引擎:MapReduce、Spark
- 流式计算引擎:Storm、Flink
- OLAP:persto、impala、clickhouse、doris
1.2 Spark生态和特点
- 统一引擎,支持多种分布式场景
- 多语言支持,支持Python、SQL、Java、Scala、R
- 可读写丰富数据源
- 丰富灵活的API/算子
- 支持K8S/YARN/Mesos资源调度
1.3 Spark生态组件
- Spark Core:Spark核心组件,它实现了Spark的基本功能,包含任务调度、内存管理、错误恢复、与存储系统交互等模块。
- Spark SQL:用来操作结构化数据的核心组件,通过Spark SQL可以直接查询Hive、HBase等多种外部数据源中的数据。
- Spark Structured Streaming:Spark提供的流式计算框架,支持高吞吐量、可容错处理的实时流式数据处理。
- MLlib:Spark提供的关于机器学习功能的算法程序库,包括分类、回归、聚类、协同过滤算法等,还提供了模型评估、数据导入等额外的功能。
- GraphX:Spark提供的分布式图处理框架,拥有对图计算和图挖掘算法的API接口以及丰富的功能和运算符。
- 独立调度器、Yarn、Mesos、Kubernetes:Spark框架可以高效地在一个到数千个节点之间伸缩计算,集群管理器则主要负责各个节点的资源管理工作,为了实现这样的要求,同时获得最大灵活性,Spark支持在各种集群管理器(Cluster Manager)上运行。
1.4 Spark运行架构和工作原理
- Application:Spark上运行的应用。Application中包含一个驱动器(Driver)进程和集群上的多个执行器(Executor)进程。
- Driver Program(驱动器) :运行main方法并创建SparkContext的进程。
- Cluster Manager(集群管理器) :用于在集群上申请资源的外部服务。
- Worker Node(工作节点):集群上运行应用程序代码的任意一个节点。
- Executor(执行器) :在集群工作节点上位某个应用启动的工作进程,该进程负责运行计算任务,并为应用程序存储数据。
- Task(任务) :执行器的工作单元。
- Job(作业): 一个并行计算作业,有一组Task组成,并由Spark的行动算子触发启动。
- Stage(阶段) :每个Job可以划分为更小的Task集合,每组任务被称为Stage。
Spark目前支持的几个集群管理器:
- Standalone:Spark附带的简单集群管理器,可以轻松设置集群。
- Hadoop YARN:Hadoop2和3 中的资源管理器。
- Kubernetes:用于自动部署、扩展和管理容器化应用程序的开源系统。
二、SparkCore原理解析
SparkCore是Spark核心组件,它实现了Spark的基本功能,包含任务调度、内存管理、错误恢复、与存储系统交互等模块。
2.1 RDD概述
-
RDD是弹性分布式数据集,是一个容错的、并行的数据结构。
-
描述RDD的五大要素
- 分区列表
- 每一个分区的计算函数
- 依赖关系
- key-value数据类型的RDD分区器
- 每个分区都有一个优先位置列表,即首选位置
-
RDD算子:对任何函数进行某一项操作都可以认为是一个算子,RDD算子是RDD的成员函数
-
RDD算子的分类:
- Transform 算子:生成一个新的RDD
- Action 算子:触发Job(作业)的提交,将在数据集上运行计算后的数值返回到驱动程序,从而触发真正的计算
-
RDD依赖:描述父子RDD之间的依赖关系
- 窄依赖:父RDD的每个partition至多对应一个子RDD分区。
- 宽依赖:父RDD的每个partition都可能对应多个子RDD分区。
2.2 RDD的执行流程
- 当RDD对象创建后,SparkContext会根据RDD对象创建DAG(有向无环图),然后将Task(任务)提交给DAGScheduler;
- DAGScheduler根据ShuffleDependency将DAG划分为不同的Stage,为每个Stage生成TaskSet任务集合,并以TaskSet为单位提交给TaskScheduler;
- TaskScheduler根据调度算法对多个TaskSet进行调度,并通过集群中的资源管理器,把Task调度到集群中的Worker的Executor,Executor由SchedulerBackend提供。
2.3 内存管理
Executor内存主要有两类:Storage、Execution
- UnifiedMemoryManager 统一管理Storage/Exection内存
- Storage 和 Execution 内存使用是动态调整,可以相互借用
- 当Storage空闲,Execution可以借用Storage的内存使用,可以减少spill等操作,Execution使用的内存不能被Storage驱逐
- 当Execution空闲,Storage可以借用Execution的内存使用
- 当Execution需要内存时,可以驱逐被Storage借用的内存,知道spark.memory.storage.Fraction边界
三、SparkSQL原理解析
3.1 SparkSQL概述
- DataFrame:是一种以RDD为基础的分布式数据集,被称为SchemaRDD
- Catalyst:SparkSQL核心模块,主要是对执行过程中的执行计划进行处理和优化
- DataSource:SparkSQL支持通过DataFrame接口对各种数据源进行操作
- Adaptive Query Execution:自适应查询执行
- Runtime Filter:运行时过滤
3.2 SparkSQL的执行流程
- SQL 解析:将SparkSQL字符串或DataFrame解析为一个抽象语法树(AST),即Unresolved Logical Plan(未解析的逻辑计划);
- Analysis:解析后的逻辑计划,节点中绑定了各种优化信息。将Unresolved Logical Plan解析成Analyzed Logical plan;
- Logical Optimization:该模块是Catalyst的核心,主要分为RBO和CBO两种优化策略,其中RBO是基于规则优化,CBO是基于代价优化。将Analyzed Logical plan解析成Optimized Logic plan。
- Physical Planning: Logical plan是不能被spark执行的,这个过程是把Logic plan转换为多个Physical plans;
- CostModel: 主要根据过去的性能统计数据,选择最佳的物理执行计划(Selected Physical Plan)。
- Code Generation: sql逻辑生成Java字节码
3.2 Catalyst 优化器
- RBO:基于规则优化
- CBO:基于代价优化
3.3 Adaptive Query Execution(AQE)
Adaptive Query Execution:自适应查询执行
AQE对于整体的Spark SQL的执行过程做了相应的调整和优化,它最大的亮点是可以根据已经完成的计划结点真实且精确的执行统计结果来不停的反馈并重新优化剩下的执行计划。
AQE支持的三种优化场景:
- 动态合并Shuffle分区
- 动态调整Join策略
- 动态优化数据倾斜Join
四、业界挑战与实践
-
Shuffle稳定性问题
在大规模作业下,开源ExternalShuffleService的实现机制容易带来大量随机读导致的磁盘IOPS瓶颈、Fetch请求积压等问题,进而导致运算过程中经常会出现Stage重算甚至作业失败,继而引起资源使用的恶性循环、严重影响SLA。
-
SQL执行性能解决方向
-
参数推荐/作业诊断
Spark参数很多,资源类/Shuffle/Join等,调参难度大;参数不合理的作业,对资源利用率/Shuffle稳定性性能有非常大影响,同时,线上作业失败/运行慢,用户排查难度大。
五、个人总结与思考
通过本课程,理解了SparkCore和SparkSQL的基本原理,对Shuffle原理有了大致的了解,Spark Shuffle机制掌握的不够透彻。Spark是集批式计算和流式计算一体的计算引擎,具有许多优秀的特性,而Spark on K8S 的出现,使得Spark在云原生方向上占据一席之地,期待Spark在云原生时代上的进化。大数据框架不断更新迭代演进,打造更好的云原生大数据框架必定会是未来的发展方向。
\