Spark 原理与实践 | 青训营笔记
这是我参与「第四届青训营 」笔记创作活动的第4天
重点内容:
一、Spark处理引擎介绍
Spark具有 Hadoop MapReduce具有的优点,不同于MapReduce的是——job中间输出可以保存在内存中,从而不在需要读写HDFS,因此Spark更加适合机器学习和数据挖掘等需要迭代的MapReduce的算法。
Spark 启用了内存分布数据集,除了能够提供交互式查询外,它还可以优化迭代工作负载。
Spark运行架构和工作原理
Spark应用程序以进程集合为单位在分布式集群上运行,通过driver程序的main方法创建的SparkContext对象与集群交互。
1、Spark通过SparkContext向Cluster manager申请所需执行的资源(cpu、内存等)
2、Cluster manager可以分配应用程序执行需要的资源,在Worker节点上创建Executor
3、SparkContext 将程序代码(jar包或者python文件)和Task任务发送给Executor计算执行,并收集结果反馈给Driver。
二、SparkCore解析
1、什么是RDD
一个RDD是一个分布式对象集合, 本质上是一个只读的分区记录集合. 一个RDD可以分成多个分区, 每个分区可以在不同的集群节点上被保存, 从而实现并行处理.
2、RDD依赖
RDD依赖:描述父子RDD之间的依赖关系(lineage)
- 窄依赖
父RDD的每个partition至多对应一个子RDD分区。
- 宽依赖
父RDD的每个partition都可能对应多个子RDD分区。
3、RDD执行流程
- RDD读入外部数据源(或者内存中的集合)进行创建
- RDD经过一系列的“转换”操作,每一次都会产生不同的RDD,供给下一个“转换”使用
- 最后一个RDD经“行动”操作进行处理,并输出到外部数据源
根据 ShuffleDependency切分Stage,并按照依赖顺序调度Stage,为每个Stage生成并提交TaskSet到 TaskScheduler
在spark中,Task的类型分为2种:ShuffleMapTask和ResultTask;简单来说,DAG的最后一个阶段会为每个结果的partition生成一个ResultTask,即每个Stage里面的Task的数量是由该Stage中最后一个RDD的Partition的数量所决定的!而其余所有阶段都会生成ShuffleMapTask;之所以称之为ShuffleMapTask是因为它需要将自己的计算结果通过shuffle到下一个stage中。
4、内存管理
Executor内存主要有两类:Storage、Execution
-
UnifiedMemoryManager统一管理Storage/Execution内存
-
Storage和Execution内存使用是动态调整,可以相互借用
-
当Storage空闲,Execution可以借用Storage的内存使用,可以减少spill 等操作,Execution使用的内存不能被Storage 驱逐 当Execution空闲,Storage可以借用Execution的内存使用,
-
当Execution需要内存时,可以驱逐被Storage借用的内存,直到spark.memory.storageFraction边界
三、SparkSQL原理解析
Catalyst 优化器
SQL语句首先通过Parser模块被解析为语法树,此棵树称为Unresolved Logical Plan;Unresolved Logical Plan通过Analyzer模块借助于Catalog中的表信息解析为Logical Plan;此时,Optimizer再通过各种基于规则的优化策略进行深入优化,得到Optimized Logical Plan;优化后的逻辑执行计划依然是逻辑的,并不能被Spark系统理解,此时需要将此逻辑执行计划转换为Physical Plan
注:
-
Parser:Parser简单来说是将SQL字符串切分成一个一个Token,再根据一定语义规则解析为一棵语法树。Parser模块目前基本都使用第三方类库ANTLR进行实现,比如Hive、 Presto、SparkSQL等。
-
Analyzer:通过解析后的逻辑执行计划基本有了骨架,但是系统不知道语句中表的字段函数等信息,此时需要基本的元数据信息来表达这些词素,最重要的元数据信息主要包括两部分:表的Scheme和基本函数信息,表的scheme主要包括表的基本定义(列名、数据类型)、表的数据格式(Json、Text)、表的物理位置等,基本函数信息主要指类信息。Analyzer会再次遍历整个语法树,对树上的每个节点进行数据类型绑定以及函数绑定。
AQE
- Partiiton合并,优化shuffle读取,减少reduce task个数
- SMJ -> BHJ
- Skew Join优化
Runtime Filter
Runtime Filter减少了大表的扫描,shuffle的数据量以及参加Join的数据量,所以对整个集群IO/网络/CPU有比较大的节省(10TB TPC-DS获得了大约35%的改进)
Codegen
Codegen是从提高cpu的利用率的角度来进行runtime优化。