在進行本篇之前,如果還有對Spark的一些基礎概念不太明白的可以參考一下這篇博文:
Spark核心組件、運行架構
RDD的依賴
RDD是一種彈性分佈式數據集,我們以圖示的形式來展示一下它的原理:
RDD的寬窄依賴
Lineage:血統、遺傳
- RDD最重要的特性之一,保存了RDD的依賴關係;
- RDD實現了基於Lineage的容錯機制;
依賴關係
寬依賴:一個父RDD的分區被子RDD的多個分區使用;
窄依賴:一個父RDD的分區被子RDD的一個分區使用;
例如union:
常見的寬依賴有:groupByKey,partitionBy,reduceByKey,Join(父RDD不是hash-partitioned :除此之外的,rdd 的join api是寬依賴)。
常見的窄依賴有:map,filter,union,mapPartitions,mapValues,join(父RDD是hash-partitioned :如果JoinAPI之前被調用的RDD API是寬依賴(存在shuffle), 而且兩個join的RDD的分區數量一致,join結果的rdd分區數量也一樣,這個時候join api是窄依賴)。
寬依賴對比窄依賴
- 寬依賴對應shuffle操作,需要在運行時將同一個父RDD的分區傳入到不同的子RDD分區中,不同的分區可能位於不同的節點,就可能涉及多個節點間數據傳輸
- 當RDD分區丟失時,Spark會對數據進行重新計算,對於窄依賴只需重新計算一次子RDD的父RDD分區。相比於寬依賴,窄依賴對優化更有利。
DAG工作原理
根據RDD之間的依賴關係,形成一個DAG(有向無環圖)。
DAGScheduler將DAG劃分爲多個Stage
- 劃分依據:是否發生寬依賴(Shuffle)
- 劃分規則:從後往前,遇到寬依賴切割爲新的Stage
- 每個Stage由一組並行的Task組成
DAGScheduler
有向無環圖調度器。
- 基於DAG劃分Stage 並以TaskSet的形勢提交Stage給TaskScheduler;
- 負責將作業拆分成不同階段的具有依賴關係的多批任務;
- 最重要的任務之一就是:計算作業和任務的依賴關係,制定調度邏輯。
- 在SparkContext初始化的過程中被實例化,一個SparkContext對應創建一個DAGScheduler。
TaskSceduler:
任務調度器。將TaskSet提交給Worker(集羣)運行並返回結果;負責每個具體任務的實際物理調度。
下面來張總表供大家仔細查看:
劃分Stage的原因
數據本地化
- 移動計算,而不是移動數據;
-保證一個Stage內不會發生數據移動;
建議
Spark Shuffler過程
在分區之間重新分配數據
- 父RDD中同一分區中的數據按照算子要求重新進入子RDD的不同分區中
- 中間結果寫入磁盤
- 由子RDD拉取數據,而不是由父RDD推送
- 默認情況下,Shuffle不會改變分區數量