1 Spark运行架构
spark运行架构如下图
在具体讲解Spark运行架构之前,需要先了解几个重要的概念:
RDD:是弹性分布式数据集(Resilient Distributed Dataset)的简称,是分布式内存的一个抽象概念,提供了一种高度受限的共享内存模型;
DAG:是Directed Acyclic Graph(有向无环图)的简称,反映RDD之间的依赖关系;
Executor:是运行在工作节点(Worker Node)上的一个进程,负责运行任务,并为应用程序存储数据;
应用:用户编写的Spark应用程序;
任务:运行在Executor上的工作单元;
作业:一个作业包含多个RDD及作用于相应RDD上的各种操作;
阶段:是作业的基本调度单位,一个作业会分为多组任务,每组任务被称为“阶段”,或者也被称为“任务集”。
在Spark中,一个应用(Application)由一个任务控制节点(Driver)和若干个作业(Job)构成,一个作业由多个阶段(Stage)构成,一个阶段由多个任务(Task)组成。当执行一个应用时,任务控制节点会向集群管理器(Cluster Manager)申请资源,启动Executor,并向Executor发送应用程序代码和文件,然后在Executor上执行任务,运行结束后,执行结果会返回给任务控制节点,或者写到HDFS或者其他数据库中
spark执行时流程可以总结为以下三步:
有向无环图是RDD之间的关系表示。
当行动操作触发计算时,Spark调度器提交一个作业来计算所有必要的RDD。这个作业包含一个或多个步骤,每个步骤就是一批并行执行的计算任务,一个步骤可能包含有向无环图中的一个或多个RDD(可能的优化:流水线执行,后面详细描述)。
2 示例说明
通过在scala-shell进行一个示例程序进行说明。
input.txt是位于spark安装目录bin目录下的一个文件,包含了若干条日志。上述代码功能是统计各个级别日志的条数。
我们知道,spark是惰性计算的,在上述代码中,前3个步骤没有执行任何行动操作,没有触发真正的计算。此时程序只是生成了一个RDD对象的有向无环图(DAG)。打开http://localhost:4040可以看到这个job对应的DAG可视化展示:
每个RDD都会维护一个指向其一个或多个父节点的引用。可以在scala-shell控制台使用toDebugString方法来查看RDD谱系:
当调用collect时,spark调度器会创建出用于计算行动操作的RDD物理执行计划。
Spark调度器会从最终被调用行动操作的RDD出发,向上回溯所有必须计算的RDD。调度器会访问父节点,父节点的父节点递归生成计算所有必要的祖先RDD的物理计划。最后以相反的顺序执行这些步骤。
优化-流水线优化
但是,spark为了提高执行效率,调度器可能会进行流水线执行(pipeline),或者把多个RDD合并到一个步骤中。当RDD不需要混洗数据即可从父节点中计算出来时,会自动进行流水线计算。我们可以从toDebugString输出的不同缩进等级看到RDD是否会在物理步骤中进行流水线执行:执行计划输出的缩进等级与父节点相同的RDD会与其父节点在同一个步骤中进行流水线执行。比如上面的counts2,从缩进看只有2级,这表明物理执行只需要两个步骤。
优化-短路求值
另外一种优化,当一个RDD已经缓存在集群内或磁盘上,spark内部调度器会自动截断RDD谱系图。在这种情况下spark会短路求值,直接基于缓存的RDD进行计算。
3 参考资料
(1)《Spark快速大数据分析》
(2)Spark入门:Spark运行架构-厦门大学数据库课程
领取专属 10元无门槛券
私享最新 技术干货