大数据-复习笔记-5 | 青训营笔记

290 阅读7分钟

Spark 原理与实践-复习笔记

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

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

1.1 大数据技术栈

  1. 应用————Bl报表/实时大盘/广告/推荐
  2. 计算————Spark/Flink/Presto/lmpala/ClickHousel... YARN/K8S
  3. 存储————MetaStore Parquet/ORC/DeltaLake/Hudi/Iceberg... HDFS/Kafka/HBase/Kudu/TOS/S3/...
  4. 数据————Velume/VarietyVelocity On-Premise/On-Cloud 平台/管理/安全/...

1.2 常见大数据处理链路

数据源——>数据采集——>分布式数据库(原始数据)——>数据处理(多次读写等操作)——>数据计算——>数据应用

1.3 开源大数据处理引擎

  1. Batch
    hadoop Map Reduce、Spark

  2. Streaming
    Flink

  3. OLAP
    presto、ClickHouse、Impala、DORIS

1.4 什么是Spark

  1. Apache Spark is a multi-language engine for executing data engineering, data science, and machine learning on single-node machines or clusters.
  2. Key features
  • Batch/streaming
    • data Unify the processing of your data inbatches and real-time streamingusing your prefered language:Python sQL Scala,Java or R.
  • SQL analytics
    • Execute fast, distributed ANSI SQL queries for dashboarding and ad-hoc reporting. Runs faster than most data warchouses.
  • Data science at scale
    • Perform Exploratory Data Analysis (EDA)on petabyte-scale data without having to resort to downsampling
  • Machine learning
    • Train machine learning algorithms on a laptop and use the same code to scale to fault-tolerant clusters of thousands of machines.

1.5 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.6 Spark 运行架构和工作原理

  • Application(应用):Spark上运行的应用。Application中包含了一个驱动器(Driver)进程和集群上的多个执行器(Executor)进程。
  • Driver Program(驱动器):运行main0方法并创建SparkContext的进程。
  • Cluster Manager(集群管理器):用于在集群上申请资源的外部服务(如:独立部署的集群管理器、Mesos或者Yarn)。
  • Worker Node(工作节点):集群上运行应用程序代码的任意一个节点。
  • Executor(执行器):在集群工作节点上为某个应用启动的工作进程,该进程负责运行计算任务,并为应用程序存储数据。
  • Task(任务):执行器的工作单元。
  • Job(作业):一个并行计算作业,由一组任务(Task)组成,并由Spark的行动(Action)算子(如:save、collect)触发启动。
  • Stage(阶段):每个Job可以划分为更小的Task集合,每组任务被称为Stage。

1.7 Spark目前支持几个集群管理器

  • Standalone:Spark 附带的简单集群管理器,可以轻松设置集群。
  • Apache Mesos:通用集群管理器,也可以运行Hadoop MapReduce 和服务应用程序。(已弃用)
  • Hadoop YARN:Hadoop2和3中的资源管理器。
  • Kubernetes:用于自动部署、扩展和管理容器化应用程序的开源系统。

2. SparkCore 原理解析

2.1 SparkCore

  • RDD(Resilient Distributed Dataset):弹性分布式数据集,是一个容错的、并行的数据结构
  • RDD算子:对任何函数进行某一项操作都可以认为是一个算子,RDD算子是RDD的成员函数
  • Transform(转换)算子:根据已有RDD创建新的RDD Action(动作)算子:将在数据集上运行计算后的数值返回到驱动程序,从而触发真正的计算
  • DAG(Directed Acyclic Graph):有向无环图,Spark中的RDD通过一系列的转换算子操作和行动算子操作形成了一个DAG
  • DAGScheduler:将作业的DAG划分成不同的Stage,每个Stage都是TaskSet任务集合,并以TaskSet为单位提交给TaskScheduler。
  • TaskScheduler:通过TaskSetManager管理Task,并通过集群中的资源管理器(Standalone模式下是Master,Yarn模式下是ResourceManager)把Task发给集群中Worker的Executor
  • Shuffle:Spark中数据重分发的一种机制。

2.2 RDD(Resilient Distributed Dataset)

2.2.1 什么是RDD\

  • RDD(Resilient Distributed Dataset):弹性分布式数据集,是一个容错的、并行的数据结构。

  • Represents an immutable, partitioned collection of elements that can be operated on in parallel.

  • 描述RDD的五要素

PartitionsA list of partitions
ComputeA function for computing each split
DependenciesA list of dependencies on other RDDs
Partitionera Partitioner for key-value RDDs(e.g.to say that the RDD is hash-paaetitioned)
PreferredLocationsa list of preferred locations to compute each split on(e.g.block locations for an HDFS file)

2.2.2 如何创建RDD

  • 内置RDD
    ShuffleRDD/HadoopRDD/JDBCRDD/KafikaRDD/UnionRDD/MapPartitionsRDD/..
  • 自定义RDD
    class CustomRDD(.)extends RDD}
    实现五要素对应的函数

2.2.3 RDD算子

  • Transform 算子:生成一个新的RDD
    map/filter/flatMap/groupByKey/reduceByKey/...

  • Action 算子:触发Job提交 collect/count/take/saveAs TextFile/…

2.2.4 RDD依赖
RDD依赖:描述父子RDD之间的依赖关系(lineage)。

  • 窄依赖:父RDD的每个partition至多对应一个子RDD分区。
    • NarrowDependency
      def getParents(partitionld:Int):Seq[lnt]
    • One ToOneDependency
      overide def getParents(partitionldInt):List[lnt]=List(partitionld)
    • RangeDependency
      overide def getParents(partitionld:Int):List[lnt]= if(partitionld >=outStart&&partitionld <outStart+length) List(partitionld-outStart +inStart)
    • PruneDependency
  • 宽依赖:父RDD的每个parttion都可能对应多个子RDD分区。
    • ShufleDependency

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

2.3 Scheduler

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

image.png

2.4 Memory Management

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

image.png

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

2.5 Shuffle

spark shuffle.manager->sort 
trait ShufileManager{
def registerShuffle...
def getWriter.
def getReader..
def unregisterShuffle...
}
class SortShuffleManager extends ShuffleManager

image.png

每个MapTask生成一个Shufle数据文件和一个index文件dataFile 中的数据按照partitionld进行排序,同一个partitionld的数据聚集在一起indexFile 保存了所有paritionld在dataFlle中的位置信息,方便后续ReduceTask 能Fetch 到对应 partitionld的数据

3. SparkSQL 原理解析

image.png

image.png

3.1 Catalyst 优化器

3.1.1 Catalyst 优化器-RBO

image.png Batch执行策略:
Once->只执行一次 FixedPoint>重复执行,直到plan不再改变,或者执行达到固定次数(默认100次)

private val defaultBatches=Sea(
Batch("Propagate Eapty ReLations",fixedpoint, 
    AQEPropagateEnptyRelation, ConvertTolocatRelation,
    UpdateAttributelullability), 
Batch("Dynanic Join Selection",once,Dynanic2einselection), 
Batch("Eliminate Linits",fixedPoint,EliminateLinits), 
Batch("Optinize one Row Plan",fixedpoint,Optiaizeonetowplan)):+
Batch("User Provided Runtine Optinizers",
    fixedPoint,extendedRuntineOptinizerRules:_*)

transformDown 先序遍历树进行规则匹配
transformUp 后序遍历树进行规则匹配

1659318208954.png

3.2 Adaptive Query Execution(AQE)

1659318268690.png

  • 每个Task结束会发送MapStatus信息给Driver
  • Task的MapStatus中包含当前Task Shufle产生的每个Partition的size统计信息
  • Driver获取到执行完的Stages的MapStatus信息之后,按照MapStatus中partition大小信息识别匹配一些优化场景,然后对后续未执行的Plan进行优化 目前支持的优化场景:
    • Partiton合并,优化shuffle读取,减少reduce task个数
    • SMJ->BHJ
    • Skew Join优化

3.3 Runtime Filter

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

3.4 Bloom Runtime Filter

3.5 Codegen

3.5.1 Codegen-Expression
1659318486955.png

  • 将表达式中的大量虚函数调用压平到一个函数内部,类似手写代码
  • 动态生成代码,Janino即时编译执行

3.5.2 Codegen-WholeStageCodegen

1659318619310.png

一个SQL包含多个Stage的WholeStageCodegen

4. 业界挑战与实践

4.1 Shuffle 稳定性问题

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

4.2 SQL 执行性能问题

  • 压榨CPU资源 CPU流水线/分支预测/乱序执行/SIMD/CPU缓存友好/…

4.3 参数推荐/作业诊断

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

解决方式:自动参数推荐/作业诊断