文章目录
Spark生态系统
- Spark Core:
Spark Core包含Spark的基本功能,如内存计算、任务调度、部署模式、故障恢复、存储管理等,Spark建立在统一的抽象RDD之上,使其可以以基本一致的方式应对不同的大数据处理场景 - Spark SQL:
Spark SQL允许开发人员直接处理RDD,同时也可查询Hive、HBase等外部数据源。Spark SQL的一个重要特点是其能够统一处理关系表和RDD,使得开发人员可以轻松地使用SQL命令进行查询,并进行更复杂的数据分析 - Spark Streaming:
Spark Streaming支持高吞吐量、可容错处理的实时流数据处理,其核心思路是将流式计算分解成一系列短小的批处理作业。Spark Streaming支持多种数据输入源,如Kafka、Flume和TCP套接字等 - MLlib(机器学习):
MLlib提供了常用机器学习算法的实现,包括聚类、分类、回归、协同过滤等,降低了机器学习的门槛,开发人员只要具备一定的理论知识就能进行机器学习的工作
GraphX(图计算): - GraphX是Spark中用于图计算的API
Components (组件)
每个spark application在集群上是以多个进程(a set of processes
,如dirver、executor等)记为进程组的方式运行,每个spark application的进程组是独立的,由你写的主程序(也叫做driver program
)的SparkContext
对象来协调。
具体来说,为了在集群上运行,SparkContext
可以连接到几个类型的Cluster Manager
(Spark自己的standalone、Mesos、YARN),Cluster Manager
在application之间分配资源。一旦连接,spark就获取集群上节点的executor
,executor
是运行计算和存储application数据的进程。接下来,它就会将应用程序代码(如传递给SparkContext的jar文件或python文件)发送给executor
。最后,SparkContext
将tasks
发送给executor
去执行。
有以下几点需要知道
- 每个application都有自己的
executor processes
,executor processes
在整个application周期内都会保持运行并以多线程的方式去执行task。这样做的好处是可以在scheduling side(每个driver program
调度自己的任务)和executor side(来自不同application的task在不同的jvm中运行)相互隔离application。然而,这也意味着如果不将数据写入外部存储系统,就无法在不同的Spark应用程序(SparkContext的实例)之间共享数据。 - spark与
Cluster Manager
是无关的,只要SparkContext
可以从Cluster Manager
获取到executor processes
,并且这些executor processes
可以相互通信就行。 driver program
在其整个生命周期内必须要监听和接受来自于executor processes
的连接。所以driver program
所在的节点必须要和executor processes
所在的节点在网络上是互通的。- 由于
driver program
要在集群上调度任务,所以应该运行在离计算节点很近的地方,最好是在相同的局域网内。
Glossary(术语表)
Term(术语) | Meaning(含义) |
---|---|
Application | 运行于Spark上的用户程序,由集群上的一个driver program (包含SparkContext 对象)和executor processes 组成 |
Application jar | 包含用户Spark程序的jar包。打成jar包时不要将Hadoop或Spark的lib打到jar包里,jar包在运行时spark和hadoop的lib会自动加载 |
Driver program | 运行application的main方法的进程,负责创建SparkContex t对象 |
Cluster manager | 集群资源管理器,例如standalone manager、Mesos、Yarn |
Deploy mode | 区分driver program 进程在哪里启动。"cluster"模式下,框架会在集群内部启动driver; "client"模式下,driver会在集群外部启动即会在提交spark application的client端启动。 |
Worker node | 工作节点, 集群中可以运行Spark应用程序的节点 |
Executor | worker node上为application启动的进程,用于执行task和保存数据到内存或磁盘。每个application有自己的executors(即多个executor) |
Task | 运行于Executor中的工作单元,Spark应用程序最终被划分为经过优化后的多个task的集合 |
Job | 由多个任务构建的并行计算任务,具体为Spark中的action操作,如collect,save等,即一个job对应一个action算子 |
Stage | 每个job将被拆分为更小的task集合,这些任务集合被称为stage,各stage相互依赖(类似于MapReduce中的map stage和reduce stage,只有map执行完reduce才可以执行),由于它由多个task集合构成,因此也称为TaskSet |
deploy mode中cluster和client的区别
以前的版本中用spark-submit提交任务时--master
可以指定 yarn-cluster
或者 yarn-client
,但是新版本(我此处用的是spark 2.4.5)里已经过时了。应该是用 --master yarn --deploy-mode cluster/client
.
其实上面的Glossary中的Deploy mode也说的很清除了,主要就是driver program
进程位置不同。
我们这里以 spark on yarn再重新说一遍。
首先清楚一个概念:Application Master。在YARN中,每个Application实例都有一个ApplicationMaster进程,它是Application启动的第一个容器(即Application Master也是在container中运行的),它负责和ResourceManager打交道并请求资源,获取资源之后告诉NodeManager为其启动Container。
下图就是 deploy-mode=client ,driver program
进程就运行在提交application的client端
下图就是 deploy-mode=cluster ,driver program
进程就运行在yarn集群内部的Spark Application Master里
cluster模式下,driver program
运行在AM(Application Master)中,它负责向YARN申请资源,并监督作业的运行状况。当用户提交了作业之后,就可以关掉Client,作业会继续在YARN上运行,因cluster模式不适合运行交互类型的作业;
client模式下,Application Master仅仅向YARN请求Executor,Client会和请求的Container通信来调度工作,也就是说Client不能关掉,像spark-shell就必须用client模式。
Spark和Hadoop作业之间的区别
- 在hadoop中,一个job可以分为多个task,task又可以分为map task和reduce task,其中map task的数量是由InputSplit来确定的,reduce task的数量是可以手动设置的。map/reduce task都分别在自己的container容器(即JVM进程YarnChild)中运行,当task运行完时,进程也就结束了(对应的container资源就要释放回收)
- 在Spark中,application才是用户提交的程序,正如上面的Glossary所述,一个job是对应着一个action算子(这是和MR中的job有很大区别的地方),每个job又可以分成多个stage(具体stage是如何划分的需要理清楚RDD后才知道),每个stage又是由多个task组成所以stage又称为taskset,每个task才是真正的工作单元。task是以executor进程的一个线程来工作。
MapReduce的task进程模型和Spark的task的线程模型
这里说的进程模型和线程模型指的是在同一个节点上多个task的运行模式。
无论是MapReduce和Spark,整体上看,都是多进程:MapReduce应用程序是由多个独立的Task进程组成的;Spark应用程序的运行环境是由多个独立的Executor进程构建的临时资源池构成的。
MapReduce的task多进程模型
- 每个Task运行在一个独立的JVM进程中;
- 可单独为不同类型的Task设置不同的资源量,目前支持内存和CPU两种资源;
- 每个Task运行完后,将释放所占用的资源,这些资源不能被其他Task复用,即使是同一个作业相同类型的Task。也就是说,每个Task都要经历“申请资源—> 运行Task –> 释放资源”的过程。
Spark的task的多线程模型
- 每个节点上可以运行一个或多个Executor进程;
- 每个Executor配有一定数量的slot,表示该Executor中可以同时运行多少个ShuffleMapTask或者ReduceTask;
- 每个Executor单独运行在一个JVM进程中,每个Task则是运行在Executor中的一个线程;
- 同一个Executor内部的Task可共享内存,比如通过函数
org.apache.spark.SparkContext#broadcast
广播的文件或者数据结构只会在每个Executor中加载一次,而不会像MapReduce那样,每个Task加载一次; - Executor一旦启动后,将一直运行,且它的资源可以一直被Task复用,直到Spark程序运行完成后才释放退出。
优劣势对比
总体上看,Spark采用的是经典的scheduler/workers模式,每个Spark应用程序运行的第一步是构建一个可重用的资源池,然后在这个资源池里运行所有的ShuffleMapTask和ReduceTask(注意,尽管Spark编程方式十分灵活,不再局限于编写Mapper和Reducer,但是在Spark引擎内部只用两类Task便可表示出一个复杂的应用程序,即ShuffleMapTask和ReduceTask),而MapReduce应用程序则不同,它不会构建一个可重用的资源池,而是让每个Task动态申请资源,且运行完后马上释放资源。
spark的task的多线程模型优点
- 任务启动速度快,不像MR的task进程启动很慢(可以从进程的创建和线程的创建看出)
- 同节点上同一个应用程序的所有任务运行在一个executor进程中,有利于共享内存。这非常适合内存密集型任务,尤其对于那些需要加载大量词典的应用程序,可大大节省内存
- task完成后executor的JVM还是可以重用的,不像MR的task需要经历“申请资源—> 运行Task –> 释放资源”的过程
spark的task的多线程模型缺点
- 由于同节点上所有任务运行在一个进程中,因此,会出现严重的资源争用,难以细粒度控制每个任务占用资源。与之相反的是MapReduce,它允许用户单独为Map Task和Reduce Task设置不同的资源,进而细粒度控制任务占用资源量,有利于大作业的正常平稳运行。