Spark會在用戶提交的計算邏輯中的RDD的轉換和動作來生成RDD之間的依賴關係,同時這個計算鏈也就生成了邏輯上的DAG(有向無環圖)。
RDD之間的關係可以從兩個維度來理解:一個是當前RDD是從哪些RDD轉換而來,也就是parent RDD(s)是什麼;還有就是依賴於parent RDD的哪些Partition。這個關係,就是RDD之間的依賴。根據依賴parent RDD的Partitions的依賴情況,spark將依賴分爲兩種,一種是窄依賴,一種是寬依賴。
RDD之間的依賴關係
窄依賴指的是每一個parent RDD的Partition最多被子RDD的一個Partition使用。
寬依賴指的是多個子RDD的Partition會依賴同一個parent RDD的Partition。
對於窄依賴而言,它們只是將Partition的數據根據轉換的規則進行轉化,並不涉及其他處理,可以簡單的認爲只是將數據從一個形式轉換到另一個形式。因此對於窄依賴,並不會引入昂貴的shuffle。所以執行效率會很高。如果整個DAG中存在多個連續的窄依賴,則可以將這些連續的窄依賴整合到一起連續執行,中間不執行shuffle從而提高效率,這樣的優化方式稱之爲流水線優化。此外,針對於窄依賴,如果子RDD的某個分區數據丟失,只需要找到父RDD對應依賴的分區恢復即可。
對於寬依賴而言,子RDD的Partition是parent RDD的所有Partition是parent RDD的所有Partition Shuffle的結果。
DAG的生成
原始的RDD通過一系列轉換就形成了DAG。RDD之間的依賴關係,包含了RDD由哪些Parent RDD轉換而來和它依賴parent RDD的哪些Partitions,是DAG的重要屬性。
藉助這些依賴關係,DAG可以認爲這些RDD之間形成了Lineage(血緣關係)。藉助Lineage,能保證一個RDD被計算前,它所依賴的parent RDD都已經完成了計算;同時,也是實現了RDD的容錯性,即如果一個RDD的部分或者全部的計算結果丟失了,那麼就需要重新計算這部分數據。
Spark中的stage
Spark在處理任務時,會根據依賴關係,將DAG劃分爲不同的階段(Stage)。
處理的流程是:
1.Spark在執行Transformation類型的操作時時,都不會立即執行,而是懶執行;
2.執行若干步的Transformation類型的操作後,一旦遇到Action類型的操作時,纔會真正觸發執行
3.執行時,從當前Action方法向前回溯,如果遇到窄依賴則應用流水線優化,繼續向前找,直到碰到某一個寬依賴
4.因爲寬依賴必須要進行shuffle操作,無法實現優化,所以將這一次段執行過程組裝成一個stage
5.再從當前寬依賴開始繼續向前尋找。重複剛纔步驟,從而將整個DAG劃分成若干個stage
如上圖所示,RDD(A)在生成RDD(B)的過程中執行了groupBy操作,A和B之前的依賴關係爲寬依賴,所以RDD(A)劃分爲Stage1。RDD(C)生成RDD(D)以及RDD(D)和RDD(E)在進行union操作,生成RDD(F)的過程中,其依賴關係均爲窄依賴,這兩個過程可以劃分爲stage2。
RDD(B)與RDD(F)進行join操作,生成RDD(G)的過程,存在寬依賴,所以這個過程劃分爲stage3。