Spark是一種開源的分布式并行計算框架,Spark擁有Hadoop Mapreduce計算框架的優(yōu)點。但是與Hadoop Mapreduce最大的不同就是:Hadoop Mapreduce分為兩個階段,map 和 reduce,兩個階段完了,就完了,在一個作業(yè)里能做的事情很少。而Spark是基于內(nèi)存迭代計算的,可以分為N個階段,一個階段完了可以繼續(xù)下一階段的處理,而且Spark作業(yè)的中間結果可以保存到內(nèi)存中,不用再頻繁去HDFS或其它數(shù)據(jù)源讀取數(shù)據(jù)。
1. Spark術語
Spark框架圖如下:
Spark框架圖.png
- Cluster Manager:資源管理,在集群上獲取資源的外部服務,目前主要有三種,Spark原生的資源管理Standalone,mesos,hadoop yarn
- Application:用戶編寫的應用程序
- Driver:應用程序中運行的main函數(shù)并創(chuàng)建SparkContext。創(chuàng)建的SparkContext負責與Cluster Manager通信,進行資源的申請,任務的分配與監(jiān)控,SparkContext代表Driver
- Worker:集群中可以運行應用程序的節(jié)點
- Executor:應用程序在Worker的進程,負責執(zhí)行task
- Task:被Executor執(zhí)行的工作單元,是運行Application最小的單位,多個task組合成一個stage,Task的調(diào)度和管理由TaskScheduler負責
- Job:包含多個Task組成的并行計算
- Stage:Stage:每個Job的Task被拆分成很多組Task, 作為一個TaskSet,命名為Stage。Stage的調(diào)度和劃分由DAGScheduler負責。Stage又分為Shuffle Map Stage和Result Stage兩種。Stage的邊界就在發(fā)生Shuffle的地方。
- RDD:Spark的基本數(shù)據(jù)操作抽象,可以通過一系列算子進行操作。RDD是Spark最核心的東西,可以被分區(qū)、被序列化、不可變、有容錯機制,并且能并行操作的數(shù)據(jù)集合。存儲級別可以是內(nèi)存,也可以是磁盤。
- DAGScheduler:根據(jù)Job構建基于Stage的DAG(有向無環(huán)任務圖),并提交Stage給TaskScheduler
- TaskScheduler:將Stage提交給Worker(集群)運行,每個Executor運行什么在此分配。
- 共享變量:Application在整個運行過程中,可能需要一些變量在每個Task中都使用,共享變量用于實現(xiàn)該目的。Spark有兩種共享變量:一種緩存到各個節(jié)點的廣播變量;一種只支持加法操作,實現(xiàn)求和的累加變量。
- 寬依賴:或稱為ShuffleDependency, 寬依賴需要計算好所有父RDD對應分區(qū)的數(shù)據(jù),然后在節(jié)點之間進行Shuffle。
- 窄依賴:或稱為NarrowDependency,指某個RDD,其分區(qū)partition x最多被其子RDD的一個分區(qū)partion y依賴。窄依賴都是Map任務,不需要發(fā)生shuffle。因此,窄依賴的Task一般都會被合成在一起,構成一個Stage。
2.Spark工作流程圖
架構圖.png
- spark-submit 提交了應用程序的時候,提交spark應用的機器會通過反射的方式,創(chuàng)建和構造一個Driver進程,Driver進程執(zhí)行Application程序,
- Driver根據(jù)sparkConf中的配置初始化SparkContext,在SparkContext初始化的過程中會啟動DAGScheduler和taskScheduler
- taskSheduler通過后臺進程,向Master注冊Application,Master接到了Application的注冊請求之后,會使用自己的資源調(diào)度算法,在spark集群的worker上,通知worker為application啟動多個Executor。
- Executor會向taskScheduler反向注冊。
- Driver完成SparkContext初始化
- application程序執(zhí)行到Action時,就會創(chuàng)建Job。并且由DAGScheduler將Job劃分多個Stage,每個Stage 由TaskSet 組成
- DAGScheduler將TaskSet提交給taskScheduler
- taskScheduler把TaskSet中的task依次提交給Executor
- Executor在接收到task之后,會使用taskRunner來封裝task(TaskRuner主要將我們編寫程序,也就是我們編寫的算子和函數(shù)進行拷貝和反序列化),然后,從Executor的線程池中取出一個線程來執(zhí)行task。就這樣Spark的每個Stage被作為TaskSet提交給Executor執(zhí)行,每個Task對應一個RDD的partition,執(zhí)行我們的定義的算子和函數(shù)。直到所有操作執(zhí)行完為止。
3.RDD
- RDD是Spark提供的核心抽象,全稱為Resillient Distributed Dataset,即彈性分布式數(shù)據(jù)集
- RDD在抽象上來說是一種元素集合,包含了數(shù)據(jù)。它是被分區(qū)的,分為多個分區(qū),每個分區(qū)分布在集群中的不同節(jié)點上,從而讓RDD中的數(shù)據(jù)可以被并行操作。
- RDD通常通過Hadoop上的文件,即HDFS文件或者Hive表,來進行創(chuàng)建;有時也可以通過應用程序中的集合來創(chuàng)建。
- RDD最重要的特性就是,提供了容錯性,可以自動從節(jié)點失敗中恢復過來。即如果某個節(jié)點上的RDD partition,因為節(jié)點故障,導致數(shù)據(jù)丟了,那么RDD會自動通過自己的數(shù)據(jù)來源重新計算該partition。這一切對使用者是透明
- RDD的數(shù)據(jù)默認情況下存放在內(nèi)存中的,但是在內(nèi)存資源不足時,Spark會自動將RDD數(shù)據(jù)寫入磁盤