1. 程式人生 > >Spark 中的寬依賴和窄依賴

Spark 中的寬依賴和窄依賴

Spark中RDD的高效與DAG圖有著莫大的關係,在DAG排程中需要對計算過程劃分stage,而劃分依據就是RDD之間的依賴關係。針對不同的轉換函式,RDD之間的依賴關係分類窄依賴(narrow dependency)和寬依賴(wide dependency, 也稱 shuffle dependency). 寬依賴與窄依賴

    窄依賴是指父RDD的每個分割槽只被子RDD的一個分割槽所使用,子RDD分割槽通常對應常數個父RDD分割槽(O(1),與資料規模無關)     相應的,寬依賴是指父RDD的每個分割槽都可能被多個子RDD分割槽所使用,子RDD分割槽通常對應所有的父RDD分割槽(O(n),與資料規模有關)

寬依賴和窄依賴如下圖所示:

寬依賴和窄依賴示例

相比於寬依賴,窄依賴對優化很有利 ,主要基於以下兩點:

    寬依賴往往對應著shuffle操作,需要在執行過程中將同一個父RDD的分割槽傳入到不同的子RDD分割槽中,中間可能涉及多個節點之間的資料傳輸;而窄依賴的每個父RDD的分割槽只會傳入到一個子RDD分割槽中,通常可以在一個節點內完成轉換。

    當RDD分割槽丟失時(某個節點故障),spark會對資料進行重算。         對於窄依賴,由於父RDD的一個分割槽只對應一個子RDD分割槽,這樣只需要重算和子RDD分割槽對應的父RDD分割槽即可,所以這個重算對資料的利用率是100%的;         對於寬依賴,重算的父RDD分割槽對應多個子RDD分割槽,這樣實際上父RDD 中只有一部分的資料是被用於恢復這個丟失的子RDD分割槽的,另一部分對應子RDD的其它未丟失分割槽,這就造成了多餘的計算;更一般的,寬依賴中子RDD分割槽通常來自多個父RDD分割槽,極端情況下,所有的父RDD分割槽都要進行重新計算。

        如下圖所示,b1分割槽丟失,則需要重新計算a1,a2和a3,這就產生了冗餘計算(a1,a2,a3中對應b2的資料)。

        寬依賴

以下是文章 RDD:基於記憶體的叢集計算容錯抽象 中對寬依賴和窄依賴的對比。

    區分這兩種依賴很有用。首先,窄依賴允許在一個叢集節點上以流水線的方式(pipeline)計算所有父分割槽。例如,逐個元素地執行map、然後filter操作;而寬依賴則需要首先計算好所有父分割槽資料,然後在節點之間進行Shuffle,這與MapReduce類似。第二,窄依賴能夠更有效地進行失效節點的恢復,即只需重新計算丟失RDD分割槽的父分割槽,而且不同節點之間可以平行計算;而對於一個寬依賴關係的Lineage圖,單個節點失效可能導致這個RDD的所有祖先丟失部分分割槽,因而需要整體重新計算。

【誤解】之前一直理解錯了,以為窄依賴中每個子RDD可能對應多個父RDD,當子RDD丟失時會導致多個父RDD進行重新計算,所以窄依賴不如寬依賴有優勢。而實際上應該深入到分割槽級別去看待這個問題,而且重算的效用也不在於算的多少,而在於有多少是冗餘的計算。窄依賴中需要重算的都是必須的,所以重算不冗餘。