Spark 原理与实践|青训营笔记

153 阅读6分钟

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

Spark 原理与实践

1.大数据处理引擎Spark介绍

大数据处理技术栈

fe2b9530f511eb452a860b3f9f4effe.png

常见大数据处理策略

fca21be5a1b901c7cdfe73be4aa6417.png

Spark介绍

Spark 是一种与 Hadoop 相似的开源集群计算环境

用于大规模数据处理的统一分析引擎

Spark生态&特点

生态:

  • 统一引擎,支持多种分布式场景
  • 多语言支持
  • 可读写丰富数据源
  • 丰富灵活的 API /算子
  • 支持K8S/ YARN / Mesos 资源调度

特点:

  • 多语言支持:SQL、JAVA/Scala、R、Python
  • 丰富数据源:内置DataSource、自定义DataSource
  • 丰富的APL/算子:SparkCore->RDD、SparkSQL->DataFrame

Spark运行架构和部署方式

9cac3e4bd27eb07c9c5abd07ec05f76.png

  1. Application(应用):Spark上运行的应用。Application中包含了一个驱动器(Driver)进程和集群上的多个执行器(Executor)进程。
  2. Driver Program(驱动器):整个应用管理者,负责作业调度
  3. Cluster Manager(集群管理器):控制Worker节点整个集群
  4. Worker Node(工作节点):集群上运行应用程序代码的任意一个节点。
  5. Executor(执行器):在集群工作节点上为某个应用启动的工作进程,该进程负责运行计算任务,并为应用程序存储数据。

#一个SparkComtext只有一个driver,负责作业的任务调度,运行程序的main函数

用户创建一个SparkComtext,连接到Cluster Manager,会根据用户 提交设置的参数、CPU、内存,来去分配资源。启动Executor。Driver Program会将用户程序划分为不同的Stage,每一个Stage会有完全相同Task,作用于待处理的分区。Driver Program会向Executor发送Task,会下载Task运行时的依赖,执行环境等,开始执行Task.并将实时的运行状态汇报给Driver Program,并做状态更新。

SparkCore原理解析

SparkCore

9556ded9a64c56677603a5e26b4e940.png

RDD

RDD:RDD弹性分布式数据集,是一个容错的、并行的数据结构

五个要素:

262bf64e21751ed846dd7f4cc578a1c.png

  1. RDD有不同分区,每一个分区都会被一个计算任务处理

  2. RDD 提供一系列最佳的计算位置

  3. RDD之间有一系列的依赖关系

  4. RDD实现了两种类型的分区函数(哈希、范围)

  5. RDD每个分区都会有优先分区列表

RDD创建

  • 内置RDD

  • 自定义RDD class CustomRDD(...)extends RDD {}

    实现五要素对应函数

RDD算子

RDD算子:对任何函数进行某一项操作都可以认为是一个算子,RDD算子是RDD的成员函数

两类:

  1. Transform算子:生成一个新的RD

map/filter/flatMap.....

  1. Action算子:触发Job提交

collect/count/take...

  • Transform(转换)算子: 根据已有RDD创建新的RDD
  • Action(动作)算子: 将在数据集上运行计算后的数值返回到驱动程序,从而触发真正的计算

RDD依赖

RDD依赖:描述父子RDD之间的依赖关系

  • 窄依赖:父 RDD 的每个 partition 至多对应一个子 RDD 分区。

  • 宽依赖:父 RDD 的每个 partition 都可能对应多个子 RDD 分区

RDD执行流程

Job : RDD action 算子触发 Stage :依据宽依赖划分 Task : Stage 内执行单个 partition 任务

1.jpg

划分Stage:从后往前推,遇到宽依赖就断开,划分为一个Stage。遇到窄依赖,就加入该Stage中。图最后一个阶段会为每个结果的Partition生成一个ResultTask。最后一个RDD的Partition数量决定每个Stage里面的Task数量。

调度器

当RDD对象创建后,SparkContext会根据RDD对象构建DAG有向无环图,然后将Task提交给DAGScheduler。

  1. 根据 ShuffleDependency 切分 Stage,并按照依赖顺序调度Stage,为每个Stage生成并提交 TaskSet到 TaskScheduler
  2. 根据调度算法(FIFO/FAIR)对多个TaskSet 进行调度,对于调度到的TaskSet,会将 Task 调度(locality)到相关 Executor上面执行,Executor SchedulerBackend提供

内存管理

1.jpg

  • Executor 内存主要有两类:Storage、Execution
  • UnifiedMemoryManager 统一管理 Storage/Execution 内存
  • Storage 和 Execution 内存使用是动态调整,可以相互借用
  • 当 Storage 空闲,Execution 可以借用 Storage 的内存使用
  • 可以减少 spill 等操作,Execution 使用的内存不能被 Storage 驱逐
  • 当 Execution 空闲,Storage 可以借用 Execution 的内存使用,
  • 当 Execution 需要内存时,可以驱逐被 Storage借用的内存,直到 spark.memory.storageFraction 边界

多任务间内存分配

61b966fc6da5628d40ee6ae28ba5b2a.png

  • UnifiedMemoryManager 统一管理多个并发 Task 的内存分配

  • 每个 Task 获取的内存区间为1/(2* N )~1/N,N 为当前 Executor 中正在并发运行的 task 数量

Shuffle

spark.shuffle.manager->sort

SortShuffleManager

每个 MapTask 生成一个 Shuffle 数据文件和一个 index 文件

ea7cdd0d7766acf389a047dbc893e40.png

External Shuffle Service

440ca0a6acb9c7e6489995c9bdd756b.png

shufle write 的文件被 NodeManage r 中的 Shufle Service 托管,供后续 ReduceTask 进行 shufle fetch ,如果 Executor空闲,DRA 可以进行回收

SparkSQL原理解析

66a7e4ce16e00594062808bd38c4bc5.png

ddfbacd4971b373873b7686668e675b.png

Catalyst优化器

- RBO:基于规则的优化

Batch 执行策略:

  • Once ->只执行一次
  • FixedPoint ->重复执行,直到 plan 不再改变,或者执行达到固定次数(默认100次)

- CBO:代价模型计算代价,选择最优,依赖于数据库对象的统计

AQE

AQE框架三种优化场景:

  • 动态合并shuffle分区(Dynamically coalescing shuffle partitions)

Partiiton合并,优化shuffle读取,减少reduce task个数

  • 动态调整Join策略(Dynamically switching join strategies)

SMJ -> BHJ

  • 动态优化数据倾斜Join(Dynamically optimizing skew joins)

Skew Join优化

partition合并

作业运行过程中,根据前面运行完的Stage的MapStatus中实际的 partiiton大小信息,可以将多个相邻的较小的partiiton进行动态合并,由一个Task读取进行处理

SMJ -> BHJ

  • Catalyst Optimizer优化阶段,算子的statistics估算不准确,生成的执行计划并不是最优

  • AQE运行过程中动态获取准确Join的leftChild/rightChild的实际大小,将SMJ转换为BHJ

Skew Join优化

AQE根据MapStatus信息自动检测是否有倾斜

将大的partition拆分成多个Task进行Join

Runtime Filter

select x,y from A join B on A.a=B.b*

Runtime Filter减少了大表的扫描,shufile的数据量以及参加Join的数据量,所以对整个集群1O/网络/CPU有比较大的节省(10TB TPC-DS 获得了大约 35% 的改进)

Codegen

Expression

select (a+1)a from t

WholeStageCodegen

select (a+1)a from t where a=1

火山模型

业界挑战与实践

1. shuffle的稳定性问题:

在大规模作业下,开源 ExternalShuffleService(ESS)的实现机制容易带来大量随机读导致的磁盘 IOPS 瓶颈、Fetch请求积压等问题,进而导致运算过程中经常会出现 Stage 重算甚至作业失败,继而引起资源使用的恶性循环,严重影响 SLA.

2. SQL执行性能问题:

压榨CPU资源

3. 参数推荐/作业诊断