Spark
概述:
Spark在2013年6月发行,早于Yarn的发行,所以内置一套资源调度框架。
Spark基于内存进行数据的分析计算,中间过程只要不涉及Shuffle就不会落盘,减少了磁盘IO,所以性能更高。
Spark 内置模块:
Spark Core: 封装了RDD的API,实现Spark基本不功能,即任务调度、内存管理、错误恢复、与存储系统交互。
Spark SQL :是Spark用来操作结构化数据的程序包。
Spark Streaming:用于实时数据的流式计算,提供了操作数据流的API。
独立调度器 : Spark内置的集群管理器。
Spark Mlib:机器学习功能的程序库。
Spark GraghX:用于图形并行计算和图挖掘系统的组件。
Spark特点:
运行快:基于内存,中间结果不落盘。
易用:支持Scala、Python、Java。
通用:支持SQL交互查询、流式处理、机器学习、图计算。
兼容性强:可以方便和Yarn、Mosos、Kubernetes融合。
Spark运行模式:
单机模式:在本地部署单个Spark服务,多用于测试。
说明:本地模式下,默认的调度器为FIFO。
集群模式:
<1>Standalone:
Standalone模式使用Spark自带的资源调动引擎,构建一个由Master和Worker构成的Spark集群,Spark运行在集群中。
Master:Spark特有的资源调度系统的leader,掌管整个集群的资源,类似于RM。
Worker:Spark特有资源调度系统的slave,掌握单个节点的资源信息,类似NM。
说明:Master和Worker是standalone模式下Spark的守护进程、集群资源管理者,只在standalone模式下才会有。
Spark的资源调度框架是为了自己使用是轻量级的,所以没有必要用Container,效率更高
Driver和Executor是任务的管理者。
Driver:SparkShell执行程序会启动Driver,并且SparkShell中会预加载SparkContext对象。
主要负责:将用户程序转为作业、跟踪Executor的任务运行状况、为执行器节点调度任务、UI显示应用运行状况。
Executor:任务的最终执行者。
主要负责:执行Spark的具体任务。
说明:Driver和Executor是临时程序,当有具体任务提交到Spark集群才会开启的程序。集群模式下都有。
Standalone的运行模式:
'tandalone-clien':Driver程序运行在本地节点。本地服务通过SparkSubmit提交任务时会在本地启动Driver,然后Driver
向Master注册Spark应用程序,然后Master会启动相应的Worker分配资源,并在Woker中启动Executor,Executor启动后Driver
会向其发送任务,待Executor执行完任务和会向Driver反向注册返回结果。
'standalone-cluster':Driver程序运行在集群上的某个节点,本地服务通过SparkSubmit提交任务后不会在本地启动Driver,而是直接
向Master注册Spark应用程序,然后Master会向指定的Worker发送启动Driver命令,Worker会启动Driver,Dirver启动后会向Master申请
资源,Master收到请求后会指定Worker分配资源,收到请求的Worker会启动Executor,然后Driver会向Executor发送任务,收到任务的
Executor执行完任务后会向Driver反向注册并返回结果。
Spark高可用:
只有单节点Master时存在单点故障问题,可以通过配置Spark的高可用。配置多个Master注册到Zookeeper并由zookeeper管理,当
Active的Master故障后zookeeper会将standby的Master这是为Active的状态,待故障的节点修复好重启后,会变为standby的状态,不会和当前
处于Active的Master进行状态的切换。
Spark高可用后提交任务是 Master 需要填两个,因为不知道那个是master。
<2>YARN:使用YARN组件进行资源调度与任务分配。Spark客户端直接连接Yarn,不需要额外构建Spark集群。
ExecutorLauncher:NodeManager上的一个线程,执行的还是AppMaster的main方法,类似封装了AM。
ExecutorBackend:NodeManager上的一个进程,里面封装了Executor对象。
Yarn运行模式:
'YarnClient': Dirver运行在本地。Spark-Submit提交任务后在本地启动Driver,Driver会初始化SC,并对任务进行划分。然后向RM申请启动
ExecutorLauncher,RM收到申请后会选择一台NM启动ExecutorLauncher,EL启动后会向RM申请资源,然后EL会在申请到资源的节点上
启动ExecutorBackend,EB启动后会创建Executor对象,最后Driver会向Executor发送任务,待Executor任务执行完后会向Driver
反向注册返回任务执行结果。
'YarnCluster':Driver运行在集群内。通过Spark-Submit提交任务会在本地客户端执行main方法,然后封装并向RM发送指令,RM收到请求后
会选择一台NM启动AM,AM内会启动Driver线程执行用户作业,初始化SC,并对任务进行切分。然后Driver向RM申请资源,并向申请到资源的NM启动EB,EB启动后会创建Executor对象
然后Driver向Executor分配任务,待Executor执行完任务和向Driver返回计算结果。
注意:集群模式下,Driver会和Executor进行内网通信,并且Driver启动在服务器节点比本地节点好。
Spark Yarn模式默认使用hadoop集群配置文件。
<3>Mesos:使用Mesos平台进行资源与任务的调度。
说明:Spark 3.0 还支持跑在 kubernetes(K8S) 上,K8S用来管理docker。
Spark常用端口:
4040 Spark正在运行的应用程序的端口号,运行结束看不到,每个spark应用程序会占用一个端口号,再来一个会累加。
7077 是 Master 和 Worker的内部通信端口。
8032 RM 和 NM 的内部通信端口。
8080 Master的默认web配置高可用时需要改,避免和ZK端口冲突。
每个worker 默认启动8个核心数, 每个executor给1g内存。
SparkContext是SparkCore的程序入口。
Spark是SparkSQL的程序入口。
'spark-submit'用于将jar包上传到集群。
'spark-shell'是一个命令工具,本身是一个Application,是一个阻塞式的sparksbumit。
SparkCore:
Spark Core中封装了RDD的API,实现了高效的DAG执行引擎。
RDD:弹性分布式数据集,是spark中最基本的数据抽象,是一个抽象类,里面存储了用来获取数据的逻辑,并没有存数据。
特性:
<1>'一组分区':是数据集的基本组成单位,用来标记数据是那个分区的。
<2>'一个计算每个分区的函数':分区之间独立计算,并行执行,互不干扰,每个分区都要执行一次RDD逻辑。
<3>'RDD之间的依赖关系' : RDD之间存在着依赖关系和血缘关系。
<4>'一个分区器': 是RDD的分片函数,用来控制分区数据的流向。
<5>'一个列表' :存取每个分区的优先位置,移动数据不如移动计算,除非资源不够。
RDD中封装的逻辑是不可变的,当一个RDD创建后,只能通过调用算子来获取另外一个RDD。
通过集合创建RDD如果不指明分区,默认会根据运行模式获取分区数,默认local[*]为当前CPU最大核心数, Local[K] K个核心数,Local 单线程1个核心数。
通过外部文件创建RDD的方式如果不指明分区,默认为两个分区,指明分区为最小的分区个数,而不是分区数。
Spark读取文件用的是hadoop1.X的API。
读取sequence、Object文件时时都要指明文件中数据的泛型,TextFile不需要。
创建RDD的方式:
1.通过集合创建,Parallelize(Arr)、MakrRdd(Arr)。
如果不指明分区数,默认当前CPU的总核心数,底层是totalCores。
如果指明分区,每个分区的数据:
length = 集合的长度 numSlices = 分区的个数 (0 until numSlices) => i
Start=((i * length) / numSlices).toInt
End = (((i+1) * length) / numSlices).toInt =>(start,end) => 每个分区对应的数据[start,end)。
2.通过外部文件创建,如果没有指明参数,默认2个分区,Min(2,totalCorse),如果指明了,会对文件进行切分。
3.通过调用转换算子由其他的RDD转换而来。
算子:
将问题的初始化状态通过操作进行转换为中间状态,然后再通过操作转换为完成状态。
Driver:算子以外的代码都是在Driver端执行
Executor:算子里面的代码都是在Executor端执行
序列化:
Driver和Executor位于不同的节点,Driver向Executor发送数据是会进行网络传输和进程通信,如果自定义类型时需要序列化,否则无法传输。
序列化方式:
<1>继承Serializable。
<2>声明为样例类,默认继承Serializable。
闭包检查:
通过RDD调用算子时,可能会用到Driver端的变量,而Spark自带闭包检查,并且在闭包检查的过程中会检查是否序列化,有闭包就需要进行序列化。
Kryo序列化:Java序列化方式比较重,Spark2.0 开始支持另外一种Kryo序列化机制。Kryo速度是Serializable的10倍。