这一篇博文是【大数据技术●降龙十八掌】系列文章的其中一篇,点击查看目录:大数据技术●降龙十八掌
Spark应用的运行架构主要分三部分:Driver、Worker Node、ClusterManager Manager。一个job是从driver开始的,driver本质上起监督的作用,保持与集群中其他实体之间的联系,并将任务提交给worker节点执行,worker节点执行executors进程,这些进程有一个或多个task。ClusterManager集群管理器负责对Application所需资源进行管理。
(1)Driver
Driver Program负责启动和管理运行Spark Job,Spark在Driver Program的main函数中,创建一个SparkContext的实例,使用SparkContext来提交Job。Driver是维护所有worker node连接的实体,并将Spark job的逻辑代码转换为物理命令。
另外,Driver维护Spark运行的上下文(context),维护程序状态、设置、可用资源等。
还有,Driver处理与集群管理器ClusterManager(比如YARN)进行通信,请求资源,一旦获得资源,Driver就会根据程序逻辑创建一个执行计划,把它提交到所分配的worker节点上,这个执行计划是包括action操作和transformation转换操作的有向无环图DAG。然后将这个DAG分解为一个个的stage(步骤),再分解为task(任务),在分解为task时候,是根据RDD数据的分区进行分解的,一个分区创建一个task。分解成了task后将这些task分配给各个worker node上executor上执行。假若Spark运行在YARN上,Driver就起Appliction Master的左右。
(2)Worker Node
Spark中,Worker Node是集群中用来运行代码的机器,一个Worker Node上运行一个或者多个executor进程,每个executor进程运行一个JVM虚拟机,封装了对CPU、内存、磁盘资源的操作,每个executor进程中创建一个或者多个task线程。
(3)Cluster Manager
Cluster Manager是个外部的服务,主要起管理资源的作用,它可能是standalone manager、Mesos,YARN。
(1) Application Jar:一个jar包包含了用户的Spark Application,一个jar包可以有很多Spark Application。
(2) Spark Application只指创建在Spark上的用户程序,包括集群上的Driver Program和Executors两部分。一个Spark Application有多个Job,Job是一个并行的计算,包含多个task,通常RDD一个Action执行时就触发一个Job。
(3) 每个Job有多个stage,每个Stage之间是相互依赖的
(4) 每个stage有多个task,每个task是一个线程,每个task业务逻辑相同,数据不同
Spark执行计算后得到的RDD结果数据,可以缓存到内存或者硬盘中,以便之后直接使用而不必再次进行计算。有两个方法可以实现缓存:cache()和persist(),二者之间的区别是cache()是将数据只是缓存到内存中,如果存不下,就只存一部分分区的数据,没有存下的数据需要重新计算。persist()方法提供了一个用于指定存储级别的API,能更加灵活地控制缓存方式。清除缓存使用unpersist()方法。
(1) persist()可以指定的存储级别有:
splitDataRdd.cache();
splitDataRdd.persist(StorageLevel.MEMORY_ONLY());
splitDataRdd.persist(StorageLevel.MEMORY_ONLY_SER());
splitDataRdd.persist(StorageLevel.MEMORY_AND_DISK());
splitDataRdd.persist(StorageLevel.MEMORY_AND_DISK_SER());
splitDataRdd.persist(StorageLevel.DISK_ONLY());
splitDataRdd.persist(StorageLevel.MEMORY_ONLY_2());
splitDataRdd.persist(StorageLevel.MEMORY_ONLY_SER_2());
splitDataRdd.persist(StorageLevel.MEMORY_AND_DISK_2());
splitDataRdd.persist(StorageLevel.MEMORY_AND_DISK_SER_2());
splitDataRdd.persist(StorageLevel.DISK_ONLY_2());
splitDataRdd.persist(StorageLevel.OFF_HEAP());
(2) 在使用缓存时需要注意:当将一个数据缓存进入内存时,如果内存不够用了,就会将其他最近最久未被使用的那个分区从内存中清除掉,虽然Spark cache是可以容错的,当使用时会重新计算丢失的数据,但是缓存了无用的数据,确实会无谓地增加执行时间。
(3) SparkSQL缓存
可以对将要多次查询的表进行缓存,表会以列式存储在内存中,这样在对表一部分列进行查询时,就不需要对整个数据集进行全部扫描。表缓存的方式有: