Spark是由加州大學伯克利分校的AMPLab於2009年開發,並於2014年成爲Apache的頂級項目,其自己是一個基於內存的分佈式處理框架,可以處理批運算,在Spark Streaming模塊的支持下,也能夠用於流式實時處理,Spark從一開始即是做爲一個生態系統出現,是一個通用的計算框架,本文參考了網上相關的spark資料,指望能對spark有個快速的全貌瞭解html
1:Spark思惟導圖java
2:支持語言python
Spark框架自己是由Scala語言編寫,這是一種相似java的語言,兼具面向對象和函數式編程特色,其編譯結果爲java字節碼,運行與java虛擬機上,並能夠直接使用Java庫,在實際開發過程當中,Spark支持Scala,Java,Python 及R 4種語言,若是使用Scala,能夠在spark-shell中方便的經過交互式方式來查詢和打草稿,若是使用python語言,也可使用pyspark shell上來執行命令和查詢算法
3:生態系統shell
Spark從誕生之初就是一個生態系統,稱之爲BDAS(伯克利數據分析棧Berkeley data analytics stack)apache
在Spark Core之上提供了4個模塊編程
SparkSQL:提供相似SQL的查詢,返回Spark DataFrame數據結構緩存
Spark Streaming:流式計算模塊,用於實時數據流處理數據結構
MLlib:機器學習模塊多線程
GraphX:基於圖的算法模塊
Spark Core:Spark 的核心模塊,提供基本的RDD及算子,DAG計算框架
4:運行模式
Spark能夠提供多種運行模式,
- 本地模式:
運行於單機上,以多線程的方式模擬Spark分佈式計算,一般用於開發階段及調試,此模式下沒有master,worker角色,參數Local[N]表示啓動N個線程,每一個線程一個core,若是不指定N,則默認是1個線程(該線程有1個core)
在本地模式中,還能夠經過修改參數,運行僞集羣模式,在單機啓動多個進程來模擬分佈式場景
單機多線程:spark-submit --class {mainClass} --master local[N] {jar file}
local[N] 指N個線程,若是設置爲local[*]則指定線程數爲cpu的邏輯內核數
單機多進程(本地僞集羣模式):spark-submit --class {mainClass} --master local[2,3,1024] {jar file}
表示2個executor,每一個executor有3個core,且分配1G內存
- 獨立模式(獨立集羣模式):這是部署spark的最簡單方式,參見 Ubuntu18.04 下 Spark 2.4.3 standalone模式集羣部署
這是Spark自帶資源調度框架,不須要依賴其餘的資源管理系統,由master,slave角色組成,使用ZooKeeper實現Master HA,在獨立模式下,有2種部署方式,client 模式及 cluster模式
- Spark on Mesos模式:
官方推薦的是Mesos,由於Spark原生的就對Mesos支持,存在2種調度模式來運行程序:粗粒度模式,細粒度模式
- Spark on YARN模式:
Spark支持YARN資源調度框架,經過使用YARN,使得Spark與Hadoop生態能很好的有機結合,又細分2種模式,yarn-cluster和yarn-client
5:Spark應用架構
Spark主要用來對大規模數據進行離線或流式處理,其自己是一種微批系統,藉助於Spark Streaming,能近乎實時的處理流式數據,Spark具有DAG執行引擎,計算模型統一基於內存RDD的屢次迭代,常部署在集羣環境下,除了能夠Standlone模式運行外,更多的是與第3方資源管理調度系統結合,如Mesos及YARN,下圖爲Spark框架:
在上面Spark架構中,能夠看到如下特定的概念:
- Application:Spark的應用程序,包含一個Driver和若干Executor
- Worker Node:實際運行Application的節點,啓動一個或多個Executor
- Driver:運行Application的main()函數而且建立SparkContext,其與ClusterManager通訊,進行資源的申請,任務分配等,Task的分發
- Executor:在Worker Node上的一個進程,該進程負責運行一個或多個Task,而且負責將數據存在內存或者磁盤上。
- Cluster Manager:在集羣上負責統一的資源管理,如Spark自動的資源管理系統,或者YARN及Mesos
- Job:SparkContext提交的每個action,會生成一個Job,Spark以最遠端的RDD爲起點(最遠端指的是對外沒有依賴的 RDD 或者 數據已經緩存下來的 RDD),到Action爲終點,造成一個DAG(有向無環圖)
- Stage:在一個Job中,Spark調度器(DAGScheduler)以shuffle類算子來劃分stage邊界,
- Task:在每一個stage中,劃分紅多個task,Driver會將Task及所依賴的file和jar序列化後傳遞到某個Executor上運行
基於YARN的Spark,因cluster及client的不一樣,其架構流程又存在差異
YARN client:Driver運行在Client中,Application Master僅向YARN請求Container,Client將和Container通訊並調度Executor
YARN cluster:Driver運行在Application Master中,其負責向YARN申請資源,並監督做業的運行情況,當用戶提交了做業以後,就能夠關閉Client,做業會繼續在YARN上運行,此模式不適合運行交互類型的做業
6:Spark核心概念
RDD(Resilent Distributed Datasets),彈性分佈式數據集,是 Spark 底層的分佈式存儲的數據結構,是 Spark 的核心概念,Spark API 的全部操做都是基於 RDD 的
對RDD的理解:
Resilent:節點失敗(分區丟失)可從新計算
Distributed:數據集被拆分到多個分區中
Dataset:能夠包含任意類型或用戶自定義對象
RDD具備如下特定:
- 是在集羣節點上的只讀不可變的、已分區的集合對象;
- 經過並行轉換的方式或外部文件讀取來建立(如 Map、 filter、join 等);
- 失敗自動重建;
- 能夠控制存儲級別(內存、磁盤等)來進行重用;
- 是可序列化的;
RDD是一種只讀數據塊,能夠經過2種方式建立
- 並行化(Parallelizing):從一個已經存在於驅動程序(Driver Program)中的集合如set、list建立
val arr = Array("help","morning","sun")
val rdd = sc.parallize(arr)
- 讀取外部數據:從外部本地文件讀取或從HDFS等讀取
val rdd= sc.textFile("D:\\temp\\holdings.txt",2)
在RDD上能夠進行函數操做,主要有2 種類型:Transformation和Action
Action操做是建立DAG的前提條件,而Transformation操做是lazy的,不會馬上執行,只有遇到Action操做纔會觸發生成DAG並執行job命令
Transformation:返回值仍是 RDD
,不會立刻 提交 Spark 集羣運行
Action:返回值不是 RDD
,會造成 DAG 圖,提交 Spark 集羣運行 並當即返回結果
常見的算子以下列表所示:
Transformation | Action |
![]()
|
![]()
|
當在RDD上應用Transformation操做時,將建立RDD Lineage,每一個RDD都包含了其是如何由父RDD變換過來的,記錄的是粗顆粒度的特定Transformation操做行爲。RDD的容錯機制稱爲「血統(Lineage)」容錯,當這個RDD的部分分區數據丟失時,能夠經過Lineage的信息來從新運算和恢復丟失的數據分區
RDD調度過程:
對於Job/Stage/Task,從DAG圖的生成到DAGScheduler--> TaskScheduler --> 最後提交到每個Executor執行,下圖清晰的表達了內部的執行邏輯
RDD依賴
在調用RDD的transformation函數時,分爲窄依賴(narrow dependency)和寬依賴(wide dependency),其區別在因而否會發生洗牌(shuffle)過程,因此寬依賴又稱爲shuffle dependency,若是RDD的每一個分區最多隻能被child RDD的一個分區使用,則爲窄依賴,若每一個分區被child RDD多個分區使用,則爲寬依賴,寬依賴將致使數據在內存中從新分佈,及多個節點間的數據傳輸,很是影響性能,是優化的關鍵點
對於這2種依賴,在Berkeley的論文RDD:基於內存的集羣計算容錯抽象中很是清晰的描述了它們的對比:
區分這兩種依賴頗有用。首先,窄依賴容許在一個集羣節點上以流水線的方式(pipeline)計算全部父分區。例如,逐個元素地執行map、而後filter操做;而寬依賴則須要首先計算好全部父分區數據,而後在節點之間進行Shuffle,這與MapReduce相似。第二,窄依賴可以更有效地進行失效節點的恢復,即只需從新計算丟失RDD分區的父分區,並且不一樣節點之間能夠並行計算;而對於一個寬依賴關係的Lineage圖,單個節點失效可能致使這個RDD的全部祖先丟失部分分區,於是須要總體從新計算。
參考: