注:本文參考文獻有書籍《Spark大數據處理:技術、應用與性能優(yōu)化》、RDD的Paper《Resilient Distributed Datasets: A Fault-Tolerant Abstraction for In-Memory Cluster Computing》。從三個部分來解讀Spark-core,首先是Spark的架構,闡述了Spark基于彈性分布式數據集RDD這個計算模型的工作機制(計算流程):Application->Job->Stage->Task 的分解、分發(fā)和并行計算;接下去從計算模型和工作機制兩個方面,分別解讀RDD的設計思想及其算子,以及劃分RDD有向無環(huán)圖為Stage和Task、并行計算的工作機制。進一步的原理分析和源碼研讀將在該系列的后續(xù)文章中撰寫。
Spark的架構
Spark采用了分布式計算中的Master-Slave模型。Master作為整個集群的控制器,負責整個集群的正常運行;Worker是計算節(jié)點,接受主節(jié)點命令以及進行狀態(tài)匯報;Executor負責任務(Tast)的調度和執(zhí)行;Client作為用戶的客戶端負責提交應用;Driver負責控制一個應用的執(zhí)行。

Spark集群啟動時,需要從主節(jié)點和從節(jié)點分別啟動Master進程和Worker進程,對整個集群進行控制。在一個Spark應用的執(zhí)行過程中,Driver是應用的邏輯執(zhí)行起點,運行Application的main函數并創(chuàng)建SparkContext,DAGScheduler把對Job中的RDD有向無環(huán)圖根據依賴關系劃分為多個Stage,每一個Stage是一個TaskSet, TaskScheduler把Task分發(fā)給Worker中的Executor;Worker啟動Executor,Executor啟動線程池用于執(zhí)行Task。

Spark的計算模型
RDD:彈性分布式數據集,是一種內存抽象,可以理解為一個大數組,數組的元素是RDD的分區(qū)Partition,分布在集群上;在物理數據存儲上,RDD的每一個Partition對應的就是一個數據塊Block,Block可以存儲在內存中,當內存不夠時可以存儲在磁盤上。

Hadoop將Mapreduce計算的結果寫入磁盤,在機器學習、圖計算、PageRank等迭代計算下,重用中間結果導致的反復I/O耗時過長,成為了計算性能的瓶頸。為了提高迭代計算的性能和分布式并行計算下共享數據的容錯性,伯克利的設計者依據兩個特性而設計了RDD:
1、數據集分區(qū)存儲在節(jié)點的內存中,減少迭代過程(如機器學習算法)反復的I/O操作從而提高性能。
2、數據集不可變,并記錄其轉換過程,從而實現無共享數據讀寫同步問題、以及出錯的可重算性。
Operations:算子
算子是RDD中定義的函數,可以對RDD中的數據進行轉換和操作。如下圖,Spark從外部空間(HDFS)讀取數據形成RDD_0,Tranformation算子對數據進行操作(如fliter)并轉化為新的RDD_1、RDD_2,通過Action算子(如collect/count)觸發(fā)Spark提交作業(yè)。
??如上的分析過程可以看出,Tranformation算子并不會觸發(fā)Spark提交作業(yè),直至Action算子才提交作業(yè),這是一個延遲計算的設計技巧,可以避免內存過快被中間計算占滿,從而提高內存的利用率。

下圖是算子的列表,分三大類:Value數據類型的Tranformation算子;Key-Value數據類型的Tranformation算子;Action算子。

Lineage Graph:血統關系圖
下圖的第一階段生成RDD的有向無環(huán)圖,即是血統關系圖,記錄了RDD的更新過程,當這個RDD的部分分區(qū)數據丟失時,它可以通過Lineage獲取足夠的信息來重新運算和恢復丟失的數據分區(qū)。DAGScheduler依據RDD的依賴關系將有向無環(huán)圖劃分為多個Stage,一個Stage對應著一系列的Task,由TashScheduler分發(fā)給Worker計算。

Spark的工作機制
本模塊從六個方面,介紹Spark的內部運行機制。
應用執(zhí)行機制
Spark應用(Application)是用戶提交的應用程序,執(zhí)行模式有Local、Standalone、YARN、Mesos。根據Application的Driver Program(或者YARN的AppMaster)是否在集群中運行,Spark應用的運行方式又可以分為Cluster模式和Client模式。
??Standalone模式
??Driver運行在客戶端

Driver運行在Worker


調度與任務分配
從Spark整體上看,調度可以分為4個級別,Application調度 -> Job調度 -> Stage調度 -> Task調度。

I/O機制
序列化
??塊管理
通信機制
Spark在模塊間通信使用的是AKKA框架。AKKA基于Scala開發(fā),用于編寫Actor應用。Actors是一些包含狀態(tài)和行為的對象。它們通過顯式傳遞消息來進行通信,這些消息會被發(fā)送到它們的收信箱中(消息隊列)。
容錯機制
Lineage機制:記錄粗粒度的更新
??Checkpoint機制:將RDD寫入Disk做檢查點。檢查點的本質是作為Lineage做容錯的輔助,lineage過長會造成容錯成本過高。在計算的中間階段做檢查點容錯,如果之后的節(jié)點出現問題而丟失分區(qū),從做檢查點的RDD開始重做Lineage,就可以減少開銷。
Shuffle機制
當單進程空間無法容納所有計算數據進行計算時,通過Shuffle將各個節(jié)點上相同的key拉取到某個節(jié)點上的一個task來進行處理,比如按照key進行聚合或join等操作。此時如果某個key對應的數據量特別大的話,就會發(fā)生數據傾斜。數據傾斜是Spark性能優(yōu)化的一個重大課題。
??可能會觸發(fā)shuffle操作的算子 :distinct、groupByKey、reduceByKey、aggregateByKey、join、cogroup、repartition等。
??Shuffle分為兩個階段:Shuffle Write和Shuffle Fetch。如下圖:
