對spark rdd 寬窄依賴的理解

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的數據)。

對spark rdd 寬窄依賴的理解

以下是文章 中對寬依賴和窄依賴的對比。

區分這兩種依賴很有用。

首先,窄依賴允許在一個集群節點上以流水線的方式(pipeline)計算所有父分區。例如,逐個元素地執行map、然後filter操作;而寬依賴則需要首先計算好所有父分區數據,然後在節點之間進行Shuffle,這與MapReduce類似。

第二,窄依賴能夠更有效地進行失效節點的恢復,即只需重新計算丟失RDD分區的父分區,而且不同節點之間可以並行計算;而對於一個寬依賴關係的Lineage圖,單個節點失效可能導致這個RDD的所有祖先丟失部分分區,因而需要整體重新計算。

之前一直理解錯了,以為窄依賴中每個子RDD可能對應多個父RDD,當子RDD丟失時會導致多個父RDD進行重新計算,所以窄依賴不如寬依賴有優勢。

而實際上應該深入到分區級別去看待這個問題,而且重算的效用也不在於算的多少,而在於有多少是冗餘的計算。窄依賴中需要重算的都是必須的,所以重算不冗餘。

窄依賴的函數有:map, filter, union, join(父RDD是hash-partitioned ), mapPartitions, mapValues

寬依賴的函數有:groupByKey, join(父RDD不是hash-partitioned ), partitionBy


分享到:


相關文章: