主页 > 新闻资讯 > 大数据学习:Spark底层运行流程解读

大数据学习:Spark底层运行流程解读

作者:张老师 浏览次数: 2021-05-10 17:05
Spark作为分布式大数据计算引擎,从大的层面来说,是继承了Hadoop MapReduce的计算模型,分为map和reduce两个阶段,而在底层核心,其运行流程就要更复杂了。今天的大数据学习分享,我们就主要来讲讲,Spark底层运行流程解读。

首先,从代码角度看DAG图的构建

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底层运行流程解读

Spark内核会在需要计算发生的时刻绘制一张关于计算路径的有向无环图,也就是如上图所示的DAG。

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

第一步,将DAG划分为Stage核心算法

一个Application可以有多个job多个Stage:

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

划分依据:

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

核心算法:回溯算法

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

Spark内核会从触发Action操作的那个RDD开始从后往前推,首先会为最后一个RDD创建一个Stage,然后继续倒推,如果发现对某个RDD是宽依赖,那么就会将宽依赖的那个RDD创建一个新的Stage,那个RDD就是新的Stage的最后一个RDD。

然后依次类推,继续倒推,根据窄依赖或者宽依赖进行Stage的划分,直到所有的RDD全部遍历完成为止。

第二步,将DAG划分为Stage剖析

大数据学习:Spark底层运行流程解读

一个Spark程序可以有多个DAG(有几个Action,就有几个DAG,上图最后只有一个Action(图中未表现),那么就是一个DAG)。

一个DAG可以有多个Stage(根据宽依赖/shuffle进行划分)。

同一个Stage可以有多个Task并行执行(task数=分区数,如上图,Stage1 中有三个分区P1、P2、P3,对应的也有三个 Task)。

可以看到这个DAG中只reduceByKey操作是一个宽依赖,Spark内核会以此为边界将其前后划分成不同的Stage。

同时我们可以注意到,在图中Stage1中,从textFile到flatMap到map都是窄依赖,这几步操作可以形成一个流水线操作,通过flatMap操作生成的partition可以不用等待整个RDD计算结束,而是继续进行map操作,这样大大提高了计算的效率。

第三步,提交Stages

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

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

大数据学习:Spark底层运行流程解读

第四步,监控Job、Task、Executor

DAGScheduler监控Job与Task:

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

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

DAGScheduler监控Executor的生命状态:

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

第五步,获取任务执行结果

结果DAGScheduler:

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

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

对于FinalStage所对应的任务,返回给DAGScheduler的是运算结果本身。

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

两种类型,DirectTaskResult与IndirectTaskResult:

根据任务结果大小的不同,ResultTask返回的结果又分为两类:

如果结果足够小,则直接放在DirectTaskResult对象内中。

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

关于大数据学习,Spark底层运行流程,以上就为大家做了基本的介绍了。Spark在大数据技术生态当中占据重要位置,想要把Spark学好,对于底层运行原理一定要理解透彻才行。成都加米谷大数据,专业大数据培训,大数据开发、数据分析与挖掘,零基础班本月正在招生中,课程大纲及预约试听可联系客服获取!
热点排行
推荐文章
立即申请>>