何炜杰
评审人:韩晶晶 徐江河
1、Spark 简介
Spark 是一种用于大规模数据处理的统一计算引擎。它是加州大学伯克利分校AMP 实验室所开发,后又成为Apache 顶级项目。围绕着Spark 还推出了Spark SQL、Spark Streaming、MLlib 和GraphX 等组件。
Spark使用Scala语言实现,它是一种面向对象的函数式编程语言,能够像操作本地集合对象一样轻松地操作分布式数据集。
2、 Spark 特点
2.1 运行速度快
Spark在批数据处理和流式数据处理方面,都有很强劲的表现,因为它使用了最先进的DAG(有向无环图)调度器、查询优化器和物理执行引擎。
官方数据表明:在逻辑回归算法中,Spark的处理速度能达到Hadoop的100多倍,这最主要是因为Spark基于内存计算和引入了DAG调度器。
2.2. 易用性好
Spark提供了超过80个高级的算子,这使得构建并行应用程序变得很容易。Spark支持多种语言进行开发,包括Scala、Java、Python等。尤其是用Scala或Python进行开发时,能用简洁的代码实现较为复杂的功能。
2.3 通用性强
Spark 提供了一系列的组件,其中Spark Core 提供内存计算框架、Spark SQL用于处理结构化数据、SparkStreaming用于实时流计算、Graphx用于图处理、MLlib用于机器学习。你能够在同一个应用程序中,组合使用这些组件,进行一站式处理。
2.4 随处运行
Spark能运行在Hadoop, Apache Mesos, Kubernetes, standalone或云端。它也能够连接各种各样的数据源,例如HDFS、HBase、Hive。
3、Spark 编程模型
3.1 RDD简介
Spark 提供的最主要的编程模型是弹性分布式数据集RDD(resilient distributed dataset),这是一种不可变的、分区的、可以并行计算的元素集合。你可以通过Hadoop文件系统上的文件或是已经存在的Scala集合来创建一个RDD,也可以通过已有的RDD来构造一个新的RDD。用户可以在内存中缓存RDD,这样可以使得它在并行计算中有效地重用。此外,RDD还能自动从节点故障中恢复。
3.2 RDD五大特性
3.2.1 分区列表
RDD被划分为很多分区分布到集群的顶点中,每一个分区都会被一个计算任务TASK处理,分区的多少决定了对这个RDD进行并行计算的粒度。
3.2.2 每个分区都有一个计算函数
Spark的RDD的计算函数是以分区为基本单位的,每个RDD都会实现 compute函数,对具体的分区进行计算。
3.2.3 依赖于其他RDD
RDD每次转换都会生成新的RDD,所以RDD之间会有前后依赖关系。正是因为有了前后的依赖关系,所以当有分区的数据丢失时,Spark 可以通过依赖关系对该分区进行重新计算,从而得出丢失的数据。而不必对所有分区都进行重新计算。
3.2.4 键值对类型的RDD有一个分区器
分区器决定了RDD如何分区,可以传入相关的参数。
3.2.5 每个分区都有一个优先位置列表
在Spark形成任务有向无环图的时候,会尽可能地把计算分配到靠近数据的位置,以减少数据网络传输。例如Hadoop 分区的首选位置就是HDFS块所在的节点。
3.3 RDD依赖
3.3.1 窄依赖
窄依赖表示每一个父RDD 中的分区最多被子RDD 的一个分区所使用。常见的窄依赖算子有:map、filter、union等。
[图片上传失败...(image-1d29c7-1542849324248)]
3.3.2 宽依赖
宽依赖表示子RDD分区依赖于父RDD的所有分区。相对于窄依赖,宽依赖付出的代价要高很多,应该尽量少使用。常见的宽依赖算子有:groupByKey、reduceByKey等。
[图片上传失败...(image-f87aa7-1542849324248)]
4、Spark 核心原理
4.1 消息通信原理
4.1.1 Spark启动消息通信
Spark启动过程中主要是进行Master和Worker之间的通信,其消息发送关系如图4-1所示。首先由Worker节点向Master节点发送注册消息。Master处理完毕后,返回注册成功或失败的消息。如果注册成功,则Worker定时发送心跳信息给Master。
avatar
4.1.2 Spark运行时消息通信
图4-2 展示了Spark运行时消息通信交互过程。用户提交应用程序时,应用程序的SparkContext会向Master发送应用注册消息,并由Master给该应用分配Executor,Executor启动后会向SparkContext发送注册成功消息。接着,TaskScheduler 会向注册的Executor发送执行消息。Executor接收到任务消息后启动并运行。最后当所有任务完成时,由Driver处理结果并回收资源。[图片上传失败...(image-7e0dd5-1542849324248)]
4.2 作业执行原理
Spark的作业调度主要是指:基于RDD的一系列操作构成一个作业,然后在Executor中执行。而对RDD的操作主要分为转换操作(Transformation)和行动操作(Action)。对于转换操作的计算是lazy级别的,也就是说它只会记录转换关系,并不会立即触发计算。只有出现了行动操作才会真正触发计算。在Spark作业中最重要的是DAGScheduler 和 TaskScheduler 两个调度器。其中DAGScheduler 负责任务的逻辑调度,而TaskScheduler 负责具体任务的调度执行。下面通过图4-1对Spark的作业和任务调度系统进行具体介绍。
[图片上传失败...(image-1cb0c2-1542849324248)]
(1)Spark应用程序进行各种转换操作,通过行动操作触发作业运行。作业提交之后根据RDD之间的依赖关系构建DAG图,DAG图提交给DAGScheduler 解析。
(2)DAGScheduler把 DAG拆分为互相依赖的调度阶段(Stage)。拆分的原则是:根据RDD的依赖是否为宽依赖,当遇到宽依赖就拆分为一个新的调度阶段。每个阶段包含的任务构成了任务集,DAGScheduler 会把这些任务集提交给TaskScheduler 进行调度。
(3)TaskScheduler 收到任务集后以任务的形式一个个分发到集群Worker节点的Executor中去运行。如果某个任务运行失败,TaskScheduler 会将其重新提交。如果某个任务运行的很慢,TaskScheduler 会再启动一个同样的任务,哪个任务先执行完就用哪个任务的结果。
(4)Worker节点中的Executor收到任务后,以多线程的方式运行,每个线程负责一个任务。
参考文献
郭景瞻 《图解Spark:核心技术与案例实战》电子工业出版社 2017-1
王家林 , 段智华 《Spark内核机制解析及性能调优》机械工业出版社 2017-1