Spark是什么?
Apache Spark 是專為大規模數據處理而設計的快速通用的計算引擎,是一種開源的類Hadoop MapReduce的通用并行框架,擁有Hadoop MapReduce所具有的優點。
Spark不同于MapReduce的是,Spark的Job中間輸出結果可以保存在內存中,從而不再需要讀寫HDFS,因此Spark能更好地適用于數據挖掘與機器學習等需要迭代的MapReduce的算法。
Spark 主要有三個特點?:
首先,高級 API 剝離了對集群本身的關注,Spark 應用開發者可以專注于應用所要做的計算本身。
其次,Spark 很快,支持交互式計算和復雜算法。
最后,Spark 是一個通用引擎,可用它來完成各種各樣的運算,包括 SQL 查詢、文本處理、機器學習等,而在 Spark 出現之前,我們一般需要學習各種各樣的引擎來分別處理這些需求。
總結一下:從各種方向上(比如開發速度和運行速度等)來看,Spark都優于Hadoop MapReduce;同時,Spark還提供大數據生態的一站式解決方案。因此,學會使用Spark刻不容緩。
目錄
Spark生態圈
Spark運行架構
Spark運行模式
Spark的Job執行流程
Spark編程模型之RDD
Spark使用的簡單Demo
Spark生態圈
首先,我們先來看一下整個Spark的生態圈,都有哪些功能。
下圖很好的說明了整個Spark的層級之間,以及同級之間的關系。(注意,此圖有些老,一些名稱已經不再使用)
從下往上看,分別是:
數據層:Spark可以運行在眾多底層的數據模型中,比如HDFS、HBASE、Amazon s3等
資源調度層:這一層是Spark的四種運行模式,包括一種本地模式local,和三種集群模式Standalone,Mesos,Yarn。
計算層:這一層是Spark的核心層,Spark Core;其計算模型基于RDD(彈性分布式數據集)
應用層:這一部分提供了基于Spark Core的高級應用,如用于交互式查詢的SparkSQL(即圖中的shark),用于流式處理的Spark Streaming,用于機器學習的MLlib和用于圖計算的GraphX等。
下圖展示的是目前的Spark的生態圈及組件。
Spark運行架構
凡是用于大數據處理的,幾乎都是主從模式(master/slave),Spark也不例外。
Spark的主節點,被稱之為Driver,其控制著整個Spark程序的應用上下文:SparkContext。
Spark的從節點,稱為Executor,負責執行具體的任務。
簡單解釋一下上圖:
1 首先Driver會創建一個SparkContext,然后和集群資源的管理者Cluster Manager進行通信,申請資源。
2 Cluster Manager會根據實際情況將合適的Worker節點分配給Spark,作為Executor使用。
3 Driver和各Executor建立連接,生成DAG圖,劃分Stage,進行Task調度;Executor則負責具體的Task執行。
Spark運行模式
Spark的運行模式往粗了說,就只有兩種:用于測試和學習的本地模式,和用于實際生產的集群模式。細分一下,集群模式主要分為Standalone,Spark on Memos,Spark on Yarn三種方式。當然還有更細的劃分方式,不過我們此處就不討論了,所以我們主要介紹下面的四種方式。
本地模式
一般是指“Local[N]”模式,其使用N個線程來進行主從模擬。不需要進行額外的參數配置,安裝好Spark之后,默認啟動的就是這種模式。
其操作全為單機完成,主要用于學習和功能測試。
Standalone
這里需要構建一個由Master+Slave構成的Spark集群,Spark運行在集群中。
這種模式是指利用Spark自己原生的master作為Cluster Manager來管理集群資源。這里需要注意的是,master并不是driver。master只擔任資源管理調度等方面的工作,具體的Task調度還是由driver完成。
Spark on Memos
Spark客戶端直接連接Mesos,不需要額外構建Spark集群,這種模式利用Memos的調度機制來管理集群。
Spark on Yarn
Spark客戶端直接連接Yarn,不需要額外構建Spark集群,這種模式是指利用Yarn的調度機制來管理集群,即上圖中的spark運行架構中的Cluster Manager為Resource Manager。
需要補充的一點是,幾種集群模式中,都有兩種細分的方式,這里以Standalone為例。
Standalone Client模式(集群)
該模式運行與集群之上,使用這種模式的時候,Master進程做為cluster manager,SparkSubmit做為Client端和運行driver程序;Worker進程用來作為Executor。
Standalone Cluster模式(集群)
該模式也是運行于集群之上,使用這種模式的時候,Client端的SparkSubmit進程會在提交任務之后退出,Client不再負責運行driver程序;Master會在集群中選擇一個Worker進程生成一個子進程DriverWrapper來啟動driver程序;同時因為DriverWrapper 進程會占用Worker進程的一個core,所以同樣的資源下配置下,會比Standalone Client模式,少用1個core來參與計算。
總結一下:Client模式中,Client提交任務之后,會作為Spark程序的driver,仍然和集群保持連接;而Cluster模式中,Client提交任務之后就退出,由集群中的某個節點擔任driver,也可以簡單理解為后臺模式。
Spark執行流程(Job的執行流程)
整個Spark執行任務,可以分為以下四個部分:
Driver端:
1 生成邏輯查詢計劃
2 生成物理查詢計劃
3 任務調度
Executor端
4 任務執行
整個流程的簡圖可以參照下圖:
如果對上面的流程有疑惑的話,可以這么考慮:
Driver端:
1 生成邏輯查詢計劃:這一步主要是根據我們對RDD的操作,比如map,join,reduce等操作,來設定RDD的查詢依賴關系。
2 生成物理查詢計劃:根據上一步的邏輯圖和數據實際分布的情況,生成整個任務實際執行的調度圖(DAG圖)。
3 任務調度:根據第二步生成的DAG圖,進行具體的任務調度。
Executor端
4 任務執行:Executor執行具體的任務
詳細的Job執行的流程圖,如下:
Spark編程模型之RDD(resilient distributed dataset)
RDD定義
RDD,彈性分布式數據集,是Spark中的數據抽象模型和編程模型,本質上是一種抽象的特殊集合 。
RDD的特點是支持多種數據來源?? 有容錯機制?? 可以被緩存?? 支持并行操作等。
在邏輯上,一個RDD代表一個數據集。而在物理上,同一個RDD里的數據可能分布在不同的節點。
下圖表示一個RDD在物理上跨節點的分布情況。
RDD創建
#RDD主要有三種方式創建
1 通過內存中的數據創建(比如內存中的數組,適合學習測試使用)
val seq=Seq(1,2,3)
val rdd=sc.makeRDD(seq)
2 通過外部數據集創建(如HDFS數據集,一般用在生產環境)
val rdd=sc.textFile("test.txt")
3 通過其他RDD轉換而來(RDD transformation)
val childRdd=rdd.map(func)
RDD操作
RDD的操作分為兩種:Transformation(轉換)操作和Action(執行)操作。其中,轉換操作會生成一個新的RDD,但這種操作是惰性的,并不會立即執行,而是生成了RDD間的相互依賴關系;執行操作一般是“寫”操作,“寫”到driver的collect()、take()和寫到文件的save()等,或者立刻需要返回結果的count()等函數;執行操作都是立即執行的。
Transformation
1 將一個RDD轉化成一個新的RDD
2 保存RDD間的依賴關系,生成DAG圖
3 惰性操作,不會立刻執行
Action
1 觸發任務的執行
RDD依賴關系
上面已經說到,RDD可以由RDD轉換而來,這樣就形成了RDD之間的相互依賴關系。根據RDD在實際執行中的表現,可以將RDD間的依賴關系分為以下兩種:
窄依賴:每個父RDD的一個Partition最多被子RDD的一個Partition所使用
寬依賴:每個父RDD的一個Partition會被多個子RDD的Partition所使用
簡單來說,窄依賴就是父子的一對一或者多對一關系,寬依賴就是父子的一對多關系。Job執行時,當窄依賴失敗時,只需要重算對應的父RDD就可以了;而當寬依賴失敗的時候,需要重算所有對應的父RDD,而重算的父RDD中,會有一些是無效的;同時,寬依賴一般會跨節點,產生大量的shuffle過程,所以要盡量減少寬依賴。
RDD的寬依賴:stage的劃分
那么,RDD的寬窄依賴有什么用呢?上面也說過,知道什么是寬依賴,并且知道寬依賴是性能瓶頸,有助于我們優化程序的執行。
其次,RDD的寬依賴,也是stage的劃分依據,如下圖所示:
Spark使用的簡單Demo
文集
文章