Spark Core进阶
一、Spark核心概念
在Spark集群概念中有一些术语是需要我们理解的:

其中重要的概念是:
1、Application
基于Spark开发的应用程序程序,一个应用程序是由一个driver和一个或者多个executors组成。
2、Driver Program
应用程序中运行的主函数,它创建了一个SparkContext。
3、Cluster manager
一个外部服务用于在集群上获取资源,比如之前我们通过spark-submit提交脚本,其中有一个参数是--master local[2]/spark://hadoop-master:7077,就是向这个local或者spark集群获取运行这个脚本任务的内存之类的资源。
4、Deploy mode
看driver运行在哪,如果是在集群里面就是cluster模式,如果driver运行在客户端就是client模式。
5、Worker node
运行应用程序的集群节点,这些Worker node就相当与Standalone模式中slaves文件中写的主机地址。
6、Executor
Application运行在Worker node上的进程;处理tasks,并且将tasks的结果存储在内存中或者硬盘中,每一个Application有它自己的Executors。
7、Task
Executor执行的最小工作单元。
8、Job
一个action对应一个job,并行的取计算由job得到的一系列的tasks。
9、Stage
每一个job并分成一系列的tasks,被称为stages。
所以,总结一下就是
(1)一个应用程序是由一个driver和一个或者多个executors组成
(2)executors是运行在Worker node上面的
(3)Worker node上面有一系列的tasks
(4)tasks是由driver发送过来的
(5)tasks是job产生的
(6)当遇到action时,会触发产生job
二、Spark运行架构

看上面的结构图有三大部分:Driver Program、Cluster Manager、Worker Node,每一个spark的应用程序在集群中运行是相互独立的,是由主程序(Driver Program)来进行协调的;当应用程序在集群上运行时,Driver Program中的SparkContext会去连接Cluster Manager(standalone cluster manager, Mesos or YARN),Cluster Manager主要就是为应用程序获取资源,诸如需要的内存之类的等;当连接后,Spark获取集群中Worker Node上的Executors,这些Executors是对你的应用程序进行运行、计算以及存储运行后的数据,那么它们运行的应用程序代码以及任务都是有SparkContext进行发送的。
需要注意的是:
- 每一个应用程序之间都是相互独立的,有它自己的Executors,也就是应用程序之间的数据是不能直接共享的,除非你将一个应用程序执行的结果先存储起来,后面的应用程序才可以使用
- Driver Program和Work node上是保持通信的状态,并且监听Executors的整个生命周期,这样也是时刻掌握Executors是否挂掉
- driver运行时应该更应该接近Work node,如果是远程,对于driver打开RPC
三、Spark与Hadoop重要概念区分

Hadoop与Spark有以下特点和区别:
1、Hadoop特点
(1)一个MR程序就是一个Job
(2)一个Job是由一个或者多个Task(Map/Reduce)组成
(3)一个Task对应一个进程
(4)Task运行时开启进程,Task执行完毕后销毁进程,对应多个Task来说,开销进程比较大
2、Spark特点
(1)一个Application是由一个Drive(main方法中创建SparkContext)和一个或者多个Executor组成的
(2)一个Application是由一个或者多个Job组成
(3)一个Job就是一个Action
(4)一个Job是由一个或者多个Stage组成
(5)一个Stage是由一个或者Task组成
(6)一个Task对应一个线程,多个Task以并行的方式运行在一个Executor中
四、Spark Cache详解
1、Cache的使用
首先启动spark,进入/root/app/spark-2.0.2-bin-hadoop2.6/bin,执行:
[root@hadoop-master bin]# ./pyspark
此时已经启动了spark,可以在web界面进行查看:
我们可以执行一个job
>>> lines= sc.textFile("file:///root/hadoopdata/wordcount.txt") >>>lines.count() 2
那么,如何对这样的一个结果进行缓存呢?Cache和Transformation是一样的都是lazy的,只有遇到Action才会执行
>>> rdd.cache() file:///root/hadoopdata/wordcount.txt MapPartitionsRDD[4] at textFile at NativeMethodAccessorImpl.java:-2 >>> rdd.count() #此时有action操作,触发上面的cache操作 2
下次再执行,就会直接从内存中取出数据:
>>> rdd.count() #速度很快
2、源码
在cache方法中:
def cache(self): """ Persist this RDD with the default storage level (C{MEMORY_ONLY}). """ self.is_cached = True self.persist(StorageLevel.MEMORY_ONLY) return self
调用的是persist方法进行持久化:
def persist(self, storageLevel=StorageLevel.MEMORY_ONLY): """ Set this RDD's storage level to persist its values across operations after the first time it is computed. This can only be used to assign a new storage level if the RDD does not have a storage level set yet. If no storage level is specified defaults to (C{MEMORY_ONLY}). >>> rdd = sc.parallelize(["b", "a", "c"]) >>> rdd.persist().is_cached True """ self.is_cached = True javaStorageLevel = self.ctx._getJavaStorageLevel(storageLevel) self._jrdd.persist(javaStorageLevel) return self
传入的参数是:StorageLevel.MEMORY_ONLY,如果删除cache那么就使用unpersist:
def unpersist(self): """ Mark the RDD as non-persistent, and remove all blocks for it from memory and disk. """ self.is_cached = False self._jrdd.unpersist() return self
这个unpersist方法是立即执行的。
比如:想改变一下缓存的策略
>>>from pyspark import StorageLevel >>>lines= sc.textFile("file:///root/hadoopdata/wordcount.txt") >>>lines.persist(StorageLevel.MEMORY_ONLY_2) >>>lines.count() #缓存执行
五、Spark Lineage详解

RDD具有血缘关系,RDD1是通过RDD0来的,如果RDD1中的partition1丢失,那么可以通过RDD0中的partition1找回,这是很好的容错机制。
六、Spark Dependency详解
1、Narrow
Narrow依赖是一个父RDD的partition最多被子RDD的某个partition使用一次,这也就意味着如果子RDD的某个pattion丢失,可以较为容易的从对应的父RDD的partition获取。

可以看到上面的三种情况都是子RDD的partition最多使用一次父RDD中的某个partition。
2、Wide
一个父RDD的partition被子RDD的partition使用多次,那么怎么判断父RDD的partition被子RDD的partition使用多次?注意使用过程中如果有shuffle过程就会出现Wide依赖。
那么什么时候会出现shuffle呢?
一般像算子中带有“ByKey”的方法需要注意,比如:groupByKey、reduceByKey以及join操作(cogroup、join)。这时会造成shuffle过程。

图一和图二中都涉及到了shuffle过程,所以就是Wide依赖。
3、实例说明
以wordcount实例说明这个过程,在wordcount中使用到的算子有flapMap、map、reduceByKey,其中前两个都是Narrow依赖,reduceByKey是Wide依赖。
以hdfs文档中WordCount.txt文档为数据源,其内容为:
hello world
hello sandy
hello world
hello sandy
hello world
hello sandy

上图中需要注意的是:
(1)reduceByKey会造成shuffle过程
(2)shuffle过程会将job分成Stage0和Stage1,也就是说凡是shuffle会将job分隔成不同的Stage(一个shuffle会有两个Stage,两个shuffle会有三个Stage)
(3)Stage中执行的就是不同的Task(比如Stage0中的flatMap和map的Task)
详情参考:http://spark.apache.org/docs/2.0.2/cluster-overview.html


浙公网安备 33010602011771号