在Spark中,RDD(彈性分布式數據集)存在依賴關系,寬依賴和窄依賴。
寬依賴和窄依賴的區別是RDD之間是否存在shuffle操作。
窄依賴
窄依賴指父RDD的每一個分區最多被一個子RDD的分區所用,即一個父RDD對應一個子RDD或多個父RDD對應一個子RDD
- map,filter,union屬於窄依賴
- 窄依賴對於流水化作業有優化效果
- 每一個RDD算子都是一個fork/join操作,join會寫入磁盤,流水線作業優化后fork,中間不join寫入磁盤
寬依賴
寬依賴指子RDD的每個分區都依賴於父RDD的多個分區
- groupby和join屬於寬依賴
- DAGScheduler從當前算子往前推,遇到寬依賴,就生成一個stage
分區划分規則
- 分區如何划分
- 分區該放到集群內哪個節點
Spark默認兩種划分器:HashPartitioner和RangePartitioner
寬依賴、窄依賴的概念不僅用在調度,對容錯也有用,如果一個節點損壞,運算是窄依賴,只要把丟失的父節點分區重新計算即可。而寬依賴的話,就需要使用checkpoint來檢查和重新計算。
邏輯上,每個RDD的算子都是一個fork/join(此join非上文的join算子,而是指同步多個並行任務的barrier):把計算fork到每個分區,算完后join,然后fork/join下一個RDD的算子。如果直接翻譯到物理實現,是很不經濟的:一是每一個RDD(即使 是中間結果)都需要物化到內存或存儲中,費時費空間;二是join作為全局的barrier,是很昂貴的,會被最慢的那個節點拖死。如果子RDD的分區到 父RDD的分區是窄依賴,就可以實施經典的fusion優化,把兩個fork/join合為一個;如果連續的變換算子序列都是窄依賴,就可以把很多個 fork/join並為一個,不但減少了大量的全局barrier,而且無需物化很多中間結果RDD,這將極大地提升性能。Spark把這個叫做流水線(pipeline)優化。