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

158 阅读3分钟

这是我参与「第四届青训营」笔记创作活动的的第5天,以下是我的课堂笔记。 本次课程主要分为四个大板块: 1. 大数据处理引擎Spark介绍
2. SparkCore原理解析
3. SparkSQL原理解析
4. 业界挑战与实践

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

1.1 大数据处理技术栈

image.png

1.2 什么是Spark

官网: spark.apache.org/
github : github.com/apache/spar…

image.png

1.3 Spark生态&特点

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

image.png

1.4 Spark特点–多语言支持

  • SQL
  • JavalScala
  • R
  • Python

1.5 Spark特点–丰富数据源

内置 DataSourc: Text、Parquet/ORC、JSON/CSV、JDBC
自定义DataSource: 实现 DataSourceV1/N2 API
HBase/Mongo/ElasticSearchl...
A community index of third-party packagefor Apache Spark.

2. SparkCore原理解析

2.1 什么是RDD

RDD(Resilient Distributed Dataset)
Represents an immutable, partitioned collection of elements that can be operated on in parallel.
(他是一个容错的,可以并行处理的分布式数据集,是spark中基本的处理模型是一个基本单元)

2.2 如何创建RDD?

  • 内置RDD
    ShuffleRDD/HadoopRDDIJDBCRDD
    /KafkaRDD/ UnionRDD/MapPartitionsRDD/...

image.png

  • 自定义RDD
    class CustomRDD(...) extends RDD{}
    实现五要素对应的函数
  • 两类RDD算子
    • Transform算子:生成一个新的RDD
      maplfilter/flatMap/groupByKey/reduceByKeyl ...

image.png

    • Action算子:触发Job提交
      collectlcount/takelsaveAsTextFilel/...

2.3 RDD依赖

RDD依赖∶描述父子RDD之间的依赖关系(lineage) \

  • 窄依赖:父RDD的每个partition至多对应一个子RDD分区。
    NarrowDependency
    def getParents(partitionld: Int): Seq[Int]
    OneToOneDeneng
    override def getParents(partitionld: Int): List[Int] =List(partitionld)
    RangeDependency
    override def getParents(partitionld: Int): List[Int]=
    if (partitionld >= outStart && partitionld<outStart + length),
    List(partitionld - outStart + inStart)
    PruneDependency \
  • 宽依赖:父RDD的每个partition都可能对应多个子RDD分区。
    √ ShuffleDependency

image.png

2.4 RDD执行流程

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

image.png

2.5 调度器

image.png 根据ShuffleDependency切分Stage,并按照依赖顺序调度Stage,为每个Stage生成并提交TaskSet到 TaskScheduler

image.png

根据调度算法(FIFO/FAIR)对多个TaskSet进行调度对于调度到的TaskSet,会将Task 调度(locality)到相关Executor上面执行,Executor SchedulerBacken提供

image.png
Locality: PROCESS_LOCAL, NODE_LOCAL, RACK_LOCAL,ANY image.png

2.6 内存管理

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

image.png

3. SparkSQL原理解析

image.png

image.png

3.1 Catalyst优化器

image.png

3.2 Adaptive Query Execution(AQE)

image.png AQE - Coalescing Shuffle Partitions:
Partition合并(coalescing shuffle partitions)

image.png

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

3.2 AQE - Switching Join Strategies

SortMergeJoin (SMJ) -> BroadcastHashJoin (BHJ)

image.png

image.png AQE根据MapStatus信息自动检测是否有倾斜
将大的partition拆分成多个Task进行Join

3.3 Runtime Filter

image.png

3.4 Bloom Runtime Filter

tpcds/q16.sql:链接
AND cs1.cs_call_center_sk=cc call center_sk

3.5 Codegen - Expression

表达式(Expression)
将表达式中的大量虚函数调用压平到一个函数内部,类似手写代码

image.png

image.png 动态生成代码,Janino 即时编译执行

4. 业界挑战与实践

4.1 Shuffle稳定性问题

image.png

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

稳定性解决方案 image.png

4.2 SQL执行性能问题

image.png

  • 压榨CPU资源
    CPU流水线/分支预测/乱序执行/SIMD/CPU缓存友好/...
    Vectorized / Codegen ?
    C++ / Java ?

4.3 参数推荐/作业诊断

Spark参数很多,资源类/Shuffle/Join/Agg/ ...
调参难度大
参数不合理的作业,对资源利用率/Shuffle稳定性/性能有非常大影响
同时,线上作业失败/运行慢,用户排查难度大 \

0174080D.png
自动参数推荐/作业诊断

5. 小结

1.大数据处理常见链路,Spark特点
2.SparkCore 中核心概念RDD,调度机制,内存管理机制,shuffle机制
3.SQL在 Spark引擎中执行的详细流程及优化方案
4.了解目前业界遇到的挑战,解决方案