Spark六:Spark 底层执行原理SparkContext、DAG、TaskScheduler

2024-01-08 15:04

本文主要是介绍Spark六:Spark 底层执行原理SparkContext、DAG、TaskScheduler,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Spark底层执行原理

学习Spark运行流程
学习链接:https://mp.weixin.qq.com/s/caCk3mM5iXy0FaXCLkDwYQ

一、Spark运行流程

在这里插入图片描述
流程:

  1. SparkContext想西苑管理器注册并向资源管理器申请运行Executor
  2. 资源管理器分配Executor,然后资源管理器启动Executor
  3. Executor发送心跳至资源管理器
  4. SparkContext构建DAG有向无环图
  5. 将DAG分解成Stage(TaskSet)
  6. 把Stage发送给TaskScheduler
  7. Executor向SparkContext申请Task
  8. TaskScheduler将Task发送给Executor运行
  9. 同时SparkContext将应用程序代码发给Executor
    10.Task在Executor上运行,运行完毕后释放所有资源

1.1 从代码角度看DAG图的构建

val session = SparkSession.builder().master("local[*]").appName().getOrCreate()
val sc = session.sparkContext
val lines1 = sc.textFile(inputPath1).map(...).map(...)
val lines2 = sc.textFile(inputPath2).map(...)
val lines3 = sc.textFile(inputPath3)val dtinone1 = lines2.union(lines3)
val dtinone = lines1.join(dtinone1)
dtinone.saveAsTextFile(...)
dtinone.filter(...).foreach(...)

代码的DAG图:
在这里插入图片描述
Spark内核会在需要计算发生的时刻绘制一张关于计算路径的有向无环图,也就是上图所示的DAG。

Spark的计算发生在RDD的Action操作,而对Action之前所有的Transformation,Spark只是记录下RDD生成的轨迹,不会触发真正的计算。

1.2 将DAG划分为Stage核心算法

一个Application可以有多个job多个Stage:
Spark Application中可以因为有不同的Action触发众多的job,一个Application中可以有很多的job,每个job是由一个或者多个Stage构成的,后面的Stage依赖于前面的Stage,也就是只有前面的Stage计算完毕后,后面的Stage才会运行。


划分依据:
Stage划分的一句是宽依赖:像像 reduceByKey,groupByKey 等算子,会导致宽依赖的产生。

宽窄依赖划分原则:
窄依赖:父 RDD 的一个分区只会被子 RDD 的一个分区依赖。即一对一或者多对一的关系,可理解为独生子女。常见的窄依赖有:map、filter、union、mapPartitions、mapValues、join(父 RDD 是 hash-partitioned)等。
宽依赖:父 RDD 的一个分区会被子 RDD 的多个分区依赖(涉及到 shuffle)。即一对多的关系,可理解为超生。常见的宽依赖有 groupByKey、partitionBy、reduceByKey、join(父 RDD 不是 hash-partitioned)等。


核心算法:回溯算法
从后往前回溯/反向解析,遇到窄依赖加入本Stage,遇到宽依赖进行Stage切分。

Spark内核会从触发Action操作的那个RDD开始,从后往前推,首先回味最后一个RDD创建要一个Stage,然后倒推,如果发现对某个RDD是宽依赖,那么会将宽依赖的那个RDD创建一个新的Stage,那个RDD就是新的Stage的最后一个RDD,以此类推继续倒推,知道所有的RDD全部遍历完成。

1.3 DAG划分为Stage剖析

具体可见 Spark二、Spark技术栈之Spark Core 第六点。

1.4 提交Stages

调度阶段的提交,最终会被转换成一个任务的提交:

  • DAGScheduler通过TaskScheduler接口提交任务集
  • 这个任务集最终会触发TaskScheduler构建一个TaskSetManager的实例来管理这个任务集的生命周期
  • 对于DAGScheduler来说,提交调度阶段的工作到此就完成了。

而TaskScheduler的具体实现则会在得到计算资源的时候,进一步通过TaskSetManager调度具体的任务到对应的Executor节点上进行运算。
在这里插入图片描述

1.5 监控Job、Task、Executor

1.5.1 DAGScheduler监控Job与Task

要保证相互依赖的作业调度阶段能够得到顺利的调度执行,DAGScheduler 需要监控当前作业调度阶段乃至任务的完成情况。


通过对外暴露一系列的回调函数实现,对于TaskScheduler来说,这些回调任务主要包括任务的开始结束失败、任务集的失败,DAGScheduler 根据这些任务的生命周期信息进一步维护作业和调度阶段的状态信息。

1.5.2 DAGScheduler 监控 Executor 的生命状态

TaskScheduler 通过回调函数通知 DAGScheduler 具体的 Executor 的生命状态,如果某一个 Executor 崩溃了,则对应的调度阶段任务集的 ShuffleMapTask 的输出结果也将标志为不可用,这将导致对应任务集状态的变更,进而重新执行相关计算任务,以获取丢失的相关数据。

1.6 获取任务执行结果

1.6.1 结果DAGScheduler

一个具体的任务在 Executor 中执行完毕后,其结果需要以某种形式返回给 DAGScheduler,根据任务类型的不同,任务结果的返回方式也不同。

1.6.2 两种结果:中间结果与最终结果

  1. 对于 FinalStage 所对应的任务,返回给 DAGScheduler 的是运算结果本身。
  2. 对于中间调度阶段对应的任务 ShuffleMapTask,返回给 DAGScheduler 的是一个 MapStatus 里的相关存储信息,而非结果本身,这些存储位置信息将作为下一个调度阶段的任务获取输入数据的依据。

1.6.3 两种类型:DirectTaskResult 与 IndirectTaskResult

按任务结果大小的不同,ResultTask返回的结果分成两类:

  1. 如果结果足够小,则直接放在 DirectTaskResult 对象内中。
  2. 如果超过特定尺寸则在 Executor 端会将 DirectTaskResult 先序列化,再把序列化的结果作为一个数据块存放在 BlockManager 中,然后将 BlockManager 返回的 BlockID 放在 IndirectTaskResult 对象中返回给 TaskScheduler,TaskScheduler 进而调用 TaskResultGetter 将 IndirectTaskResult 中的 BlockID 取出并通过 BlockManager 最终取得对应的 DirectTaskResult。

1.7 任务调度总体诠释

在这里插入图片描述

二、Spark运行架构特点

2.1 Executor进程专属

每个Application获取专属的Executor进程,该进程在Application期间一直驻留,并以多线程方式运行Tasks。

Spark Application不能跨应用程序共享数据,除非将数据写入到外部存储系统,如图所示:
在这里插入图片描述

2.2 支持多种资源管理器

Spark与资源管理器无关,只要能够获取Executor进程,并能保持互相通信就可以了。
Spark支持支援管理器包括:Standalone、On Mesos、On YARN、Or On EC2。如图所示:
在这里插入图片描述

2.3 Job提交就近原则

提交SparkContext的Client应该靠近Worker节点(运行Executor的节点),最好在同一个Rack(机架)里,因为Spark Application运行过程中SparkContext和Executor之间有大量的信息交换;

如果想在远程集群中运行,最好使用RPC将SparkContext提交给集群,不要远离Worker运行SparkContext
在这里插入图片描述

2.4 移动程序而非移动数据的原则执行

移动程序而非移动数据的原则知性,Task采用了数据本地行和推测知性的优化机制
关键方法:taskIdToLocations、getPreferedLocations。
在这里插入图片描述

这篇关于Spark六:Spark 底层执行原理SparkContext、DAG、TaskScheduler的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/583852

相关文章

解密SQL查询语句执行的过程

《解密SQL查询语句执行的过程》文章讲解了SQL语句的执行流程,涵盖解析、优化、执行三个核心阶段,并介绍执行计划查看方法EXPLAIN,同时提出性能优化技巧如合理使用索引、避免SELECT*、JOIN... 目录1. SQL语句的基本结构2. SQL语句的执行过程3. SQL语句的执行计划4. 常见的性能优

Spring Security 单点登录与自动登录机制的实现原理

《SpringSecurity单点登录与自动登录机制的实现原理》本文探讨SpringSecurity实现单点登录(SSO)与自动登录机制,涵盖JWT跨系统认证、RememberMe持久化Token... 目录一、核心概念解析1.1 单点登录(SSO)1.2 自动登录(Remember Me)二、代码分析三、

Spring Bean初始化及@PostConstruc执行顺序示例详解

《SpringBean初始化及@PostConstruc执行顺序示例详解》本文给大家介绍SpringBean初始化及@PostConstruc执行顺序,本文通过实例代码给大家介绍的非常详细,对大家的... 目录1. Bean初始化执行顺序2. 成员变量初始化顺序2.1 普通Java类(非Spring环境)(

Spring Boot 中的默认异常处理机制及执行流程

《SpringBoot中的默认异常处理机制及执行流程》SpringBoot内置BasicErrorController,自动处理异常并生成HTML/JSON响应,支持自定义错误路径、配置及扩展,如... 目录Spring Boot 异常处理机制详解默认错误页面功能自动异常转换机制错误属性配置选项默认错误处理

如何在Java Spring实现异步执行(详细篇)

《如何在JavaSpring实现异步执行(详细篇)》Spring框架通过@Async、Executor等实现异步执行,提升系统性能与响应速度,支持自定义线程池管理并发,本文给大家介绍如何在Sprin... 目录前言1. 使用 @Async 实现异步执行1.1 启用异步执行支持1.2 创建异步方法1.3 调用

在MySQL中实现冷热数据分离的方法及使用场景底层原理解析

《在MySQL中实现冷热数据分离的方法及使用场景底层原理解析》MySQL冷热数据分离通过分表/分区策略、数据归档和索引优化,将频繁访问的热数据与冷数据分开存储,提升查询效率并降低存储成本,适用于高并发... 目录实现冷热数据分离1. 分表策略2. 使用分区表3. 数据归档与迁移在mysql中实现冷热数据分

Spring Boot Maven 插件如何构建可执行 JAR 的核心配置

《SpringBootMaven插件如何构建可执行JAR的核心配置》SpringBoot核心Maven插件,用于生成可执行JAR/WAR,内置服务器简化部署,支持热部署、多环境配置及依赖管理... 目录前言一、插件的核心功能与目标1.1 插件的定位1.2 插件的 Goals(目标)1.3 插件定位1.4 核

mybatis执行insert返回id实现详解

《mybatis执行insert返回id实现详解》MyBatis插入操作默认返回受影响行数,需通过useGeneratedKeys+keyProperty或selectKey获取主键ID,确保主键为自... 目录 两种方式获取自增 ID:1. ​​useGeneratedKeys+keyProperty(推

从原理到实战深入理解Java 断言assert

《从原理到实战深入理解Java断言assert》本文深入解析Java断言机制,涵盖语法、工作原理、启用方式及与异常的区别,推荐用于开发阶段的条件检查与状态验证,并强调生产环境应使用参数验证工具类替代... 目录深入理解 Java 断言(assert):从原理到实战引言:为什么需要断言?一、断言基础1.1 语

MySQL中的表连接原理分析

《MySQL中的表连接原理分析》:本文主要介绍MySQL中的表连接原理分析,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、背景2、环境3、表连接原理【1】驱动表和被驱动表【2】内连接【3】外连接【4编程】嵌套循环连接【5】join buffer4、总结1、背景