Spark核心技术原理透视一Spark运行原理文档格式.docx
《Spark核心技术原理透视一Spark运行原理文档格式.docx》由会员分享,可在线阅读,更多相关《Spark核心技术原理透视一Spark运行原理文档格式.docx(28页珍藏版)》请在冰豆网上搜索。
Spark应用程序,由一个或多个作业JOB组成,如下图所示:
2、Driver:
驱动程序
Spark中的Driver即运行上述Application的Main()函数并且创建SparkContext,其中创建SparkContext的目的是为了准备Spark应用程序的运行环境。
在Spark中由SparkContext负责和ClusterManager通信,进行资源的申请、任务的分配和监控等;
当Executor部分运行完毕后,Driver负责将SparkContext关闭。
通常SparkContext代表Driver,如下图所示:
3、ClusterManager:
资源管理器
指的是在集群上获取资源的外部服务,常用的有:
Standalone,Spark原生的资源管理器,由Master负责资源的分配;
HaddopYarn,由Yarn中的ResearchManager负责资源的分配;
Messos,由Messos中的MessosMaster负责资源管理,如下图所示:
4、Executor:
执行器
Application运行在Worker节点上的一个进程,该进程负责运行Task,并且负责将数据存在内存或者磁盘上,每个Application都有各自独立的一批Executor,如下图所示:
5、Worker:
计算节点
集群中任何可以运行Application代码的节点,类似于Yarn中的NodeManager节点。
在Standalone模式中指的就是通过Slave文件配置的Worker节点,在SparkonYarn模式中指的就是NodeManager节点,在SparkonMessos模式中指的就是MessosSlave节点,如下图所示:
6、RDD:
弹性分布式数据集
ResillientDistributedDataset,Spark的基本计算单元,可以通过一系列算子进行操作(主要有Transformation和Action操作),如下图所示:
7、窄依赖
父RDD每一个分区最多被一个子RDD的分区所用;
表现为一个父RDD的分区对应于一个子RDD的分区,或两个父RDD的分区对应于一个子RDD的分区。
如图所示:
8、宽依赖
父RDD的每个分区都可能被多个子RDD分区所使用,子RDD分区通常对应所有的父RDD分区。
常见的窄依赖有:
map、filter、union、mapPartitions、mapValues、join(父RDD是hash-partitioned:
如果JoinAPI之前被调用的RDDAPI是宽依赖(存在shuffle),而且两个join的RDD的分区数量一致,join结果的rdd分区数量也一样,这个时候joinapi是窄依赖)。
常见的宽依赖有groupByKey、partitionBy、reduceByKey、join(父RDD不是hash-partitioned:
除此之外的,rdd的joinapi是宽依赖)。
9、DAG:
有向无环图
DirectedAcyclegraph,反应RDD之间的依赖关系,如图所示:
10、DAGScheduler:
有向无环图调度器
基于DAG划分Stage并以TaskSet的形势提交Stage给TaskScheduler;
负责将作业拆分成不同阶段的具有依赖关系的多批任务;
最重要的任务之一就是:
计算作业和任务的依赖关系,制定调度逻辑。
在SparkContext初始化的过程中被实例化,一个SparkContext对应创建一个DAGScheduler。
11、TaskScheduler:
任务调度器
将Taskset提交给worker(集群)运行并回报结果;
负责每个具体任务的实际物理调度。
12、Job:
作业
由一个或多个调度阶段所组成的一次计算作业;
包含多个Task组成的并行计算,往往由SparkAction催生,一个JOB包含多个RDD及作用于相应RDD上的各种Operation。
13、Stage:
调度阶段
一个任务集对应的调度阶段;
每个Job会被拆分很多组Task,每组任务被称为Stage,也可称TaskSet,一个作业分为多个阶段;
Stage分成两种类型ShuffleMapStage、ResultStage。
14、TaskSet:
任务集
由一组关联的,但相互之间没有Shuffle依赖关系的任务所组成的任务集。
提示:
1)一个Stage创建一个TaskSet;
2)为Stage的每个Rdd分区创建一个Task,多个Task封装成TaskSet
15、Task:
任务
被送到某个Executor上的工作任务;
单个分区数据集上的最小处理流程单元。
总体如图所示:
1、Executor进程专属
每个Application获取专属的executor进程,该进程在Application期间一直驻留,并以多线程方式运行tasks。
SparkApplication不能跨应用程序共享数据,除非将数据写入到外部存储系统。
2、支持多种资源管理器
Spark与资源管理器无关,只要能够获取executor进程,并能保持相互通信就可以了,Spark支持资源管理器包含:
Standalone、OnMesos、OnYARN、OrOnEC2。
3、Job提交就近原则
提交SparkContext的Client应该靠近Worker节点(运行Executor的节点),最好是在同一个Rack(机架)里,因为SparkApplication运行过程中SparkContext和Executor之间有大量的信息交换;
如果想在远程集群中运行,最好使用RPC将SparkContext提交给集群,不要远离Worker运行SparkContext。
4、移动程序而非移动数据的原则执行
Task采用了数据本地性和推测执行的优化机制。
关键方法:
taskIdToLocations、getPreferedLocations。
1、计算流程
2、从代码构建DAG图
Sparkprogram
Vallines1=sc.textFile(inputPath1).map(·
·
)).map(·
)
Vallines2=sc.textFile(inputPath2).map(·
Vallines3=sc.textFile(inputPath3)
Valdtinone1=lines2.union(lines3)
Valdtinone=lines1.join(dtinone1)
dtinone.saveAsTextFile(·
dtinone.filter(·
).foreach(·
Spark的计算发生在RDD的Action操作,而对Action之前的所有Transformation,Spark只是记录下RDD生成的轨迹,而不会触发真正的计算。
Spark内核会在需要计算发生的时刻绘制一张关于计算路径的有向无环图,也就是DAG。
3、将DAG划分为Stage核心算法
Application多个job多个Stage:
SparkApplication中可以因为不同的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全部遍历完成为止。
4、将DAG划分为Stage剖析
从HDFS中读入数据生成3个不同的RDD,通过一系列transformation操作后再将计算结果保存回HDFS。
可以看到这个DAG中只有join操作是一个宽依赖,Spark内核会以此为边界将其前后划分成不同的Stage.同时我们可以注意到,在图中Stage2中,从map到union都是窄依赖,这两步操作可以形成一个流水线操作,通过map操作生成的partition可以不用等待整个RDD计算结束,而是继续进行union操作,这样大大提高了计算的效率。
5、相关代码
6、提交Stages
调度阶段的提交,最终会被转换成一个任务集的提交,DAGScheduler通过TaskScheduler接口提交任务集,这个任务集最终会触发TaskScheduler构建一个TaskSetManager的实例来管理这个任务集的生命周期,对于DAGScheduler来说,提交调度阶段的工作到此就完成了。
而TaskScheduler的具体实现则会在得到计算资源的时候,进一步通过TaskSetManager调度具体的任务到对应的Executor节点上进行运算。
7、相关代码
TaskSetManager负责管理TaskSchedulerImpl中一个单独TaskSet,跟踪每一个task,如果task失败,负责重试task直到达到task重试次数的最多次数。
8、监控Job、Task、Executor
DAGScheduler监控Job与Task:
要保证相互依赖的作业调度阶段能够得到顺利的调度执行,DAGScheduler需要监控当前作业调度阶段乃至任务的完成情况。
这通过对外暴露一系列的回调函数来实现的,对于TaskScheduler来说,这些回调函数主要包括任务的开始结束失败、任务集的失败,DAGScheduler根据这些任务的生命周期信息进一步维护作业和调度阶段的状态信息。
DAGScheduler监控Executor的生命状态:
TaskScheduler通过回调函数通知DAGScheduler具体的Executor的生命状态,如果某一个Executor崩溃了,则对应的调度阶段任务集的Shuffl