1. Spark概述
Apache Spark是是一个开源的快速通用的计算框架。Spark是由UC Berkeley AMP lab所开源的类MapReduce的通用内存并行计算框架。Spark的一个重要特点就是能够在内存中计算,因而更快,即使依赖磁盘进行计算,Spark依然比MapReduce执行效率更高。
2. Spark运行模式
2.1 Local模式
在本机上执行,主要用于测试代码,运行资源仅限于本台机器。
2.2 Standalone模式
利用Spark自带的资源管理器与调度器管理Spark集群,采用Master/Slaver结构。
2.3 Yarn模式
集群运行在Yarn资源管理器上,资源管理由yarn负责,spark只负责调度和计算。
Spark on Yarn模式中,分为yarn-client和yarn-cluster模式,两者的区别在于:yarn-client的driver端在本地。yarn-cluster的driver由yarn进行分配。
2.4 Mesos模式
集群运行在Mesos资源管理器上,资源管理由Mesos负责,spark只负责调度和计算。
3. Spark运行流程
3.1 Spark中的基本概念
- ClusterManager:集群资源管理器,在Standalone模式中即为Master节点,在Yarn中就是ResourceManager.
- Application:代表你的应用程序
- Driver:主节点,运行main函数并且初始化SparkContext的节点。由SparkContext和ClusterManager通信,进行资源申请,同时对任务进行分配和监控。运行结束后关闭SparkContext。
- Worker:计算节点,负责启动Driver或者Executor,在Yarn中就是NodeManager节点。
- Executor:执行器,Application运行在Worker节点上的一个进程,该进程负责运行某些task,并且负责将数据存在内存或者磁盘上,和Yarn中的Container功能差不多。在Spark on Yarn模式中每个Excutor运行Task的并行数由分配的CPU个数控制。
- SparkContext:整个Spark程序的入口,控制应用的生命周期,2.0版本后,叫做SparkSession。
- RDD: Spark的最基本的数据抽象。
- Task:在Executor中执行任务的工作单元,多个Task组成一个Stage。
- Stage:阶段,每个Job会拆分成几个阶段执行,每个阶段代表很多Task,作为一个TaskSet,称作为Stage。
- Job:作业,由Action行为触发,例如调用RDD的一个Action算子。
- DAGScheduler:根据Job构建基于Stage的DAG,并提交Stage到TaskScheduler,划分Stage的依据是RDD之间的依赖关系。流程为:1.得到Job,2计算DAG,3划分Stage,4提交给TaskScheduler,5对Stage级别的错误进行重跑
- TaskScheduler:将Task提交给集群运行,每个Executor执行什么task由其控制。Task级别的错误由其控制
3.2 Spark基本运行流程
- Client提交任务。
- ClusterManager找到一个worker启动driver。
- driver向ClusterManager申请Executor资源。
- sparkcontext构建DAG图,将DAG分解为Stage,由DAGScheduler将TaskSet发送给TaskScheduler。
- TaskScheduer将Task分配给Executor.
- Task在Executor上运行完毕,给driver返回状态,释放资源。
3.3 Spark运行架构特点
- 每个Application有自己的executor,每个driver调度自己的任务,每个Task运行在不同的JVM,这种隔离机制使程序之间互不干扰,但这也意味着不能跨应用共享数据。
- Driver应该靠近worker节点,因为SparkContext与Executor之间有大量的信息交换。
- Task采用了数据本地性和推测执行的优化机制。
4. Spark组件
4.1 SparkCore
4.1.1 RDD
1. 什么是RDD
RDD(Resilient Distributed DataSet)弹性分布式数据集,是Spark最基本的数据抽象。RDD是一个分布在集群的节点上的不可变、可分区、可以并行计算的容错数据集合。注意:RDD存储的不是真实的数据,只是存储数据的获取方法、分区方法以及数据类型等信息。
2. 为什么叫弹性
- 自动的进行内存和磁盘的存储切换。
- 基于血统的高效容错,当节点出错时,会尝试获取上游依赖数据重新计算出错数据。
- 数据分片高度弹性,可以人工自由的设置分片(repartition)。
3. RDD的属性
- Partition,一组分区,即数据集的基本组成单位。对于RDD来说,每个分区都由一个计算任务处理,并决定并行计算的粒度。可以在创建RDD的时候指定分区个数,如果没有指定,采用默认值,默认值为程序分配到的CPU个数。
- Iterator和Compute,一个计算每个分区的函数,表示RDD是如何通过父RDD计算得到的。RDD的计算是以分区为单位的,每个RDD都会实现compute函数以达到这个目的。compute函数会对迭代器进行复合,不需要保存每次计算结果。
- Dependencies与Lineage,RDD之间的依赖和血缘关系。RDD每次转换都会生成一个新的RDD,所以RDD之间就会形成一个类似流水线一样的前后依赖关系。当部分分区数据丢失时,Spark可以依据这个依赖关系,重新计算丢失的数据,而不必对RDD所有的分区进行计算。依赖关系中又分为窄依赖和宽依赖,如果父类RDD的每个分区最多只能被子RDD的一个分区使用,称为窄依赖(NarrowDependency);如果父类RDD的每个分区可以被子RDD的多个分区使用,称为宽依赖(ShuffleDpendency),顾名思义,这其中还需要shuffle操作。
- Partitioner,RDD的分片函数,决定了RDD的分区方式。当前Spark实现了两种类型的分片函数,一个基于哈希的HashPartitioner和一个基于范围的RangePartitioner。Hash是以key作为分区条件散列分布,分区数据不连续,极端情况下散列到少数几个分区上,导致数据不均等,range按Key的排序进行均衡分布,分区内数据连续,大小也相对均等。只有key-value的RDD,才有Partitioner。Partitioner决定了RDD的分区数量