1.前言
《上一節Spark DAG概述》Spark中RDD的高效與DAG圖有着莫大的關係,在DAG調度中須要對計算過程劃分stage,
暴力的理解就是stage的劃分是按照有沒有涉及到shuffle來劃分的,沒涉及的shuffle的都劃分在一個stage裏面,
這種劃分依據就是RDD之間的依賴關係。針對不一樣的轉換函數,RDD之間的依賴關係分類窄依賴(narrow dependency)
和寬依賴(wide dependency, 也稱 shuffle dependency)
2.定義
1.窄依賴是指父RDD的每一個分區只被子RDD的一個分區所使用,子RDD分區一般對應常數個父RDD分區(O(1),與數據規模無關)
2.相應的,寬依賴是指父RDD的每一個分區均可能被多個子RDD分區所使用,子RDD分區一般對應全部的父RDD分區(O(n),與數據規模有關)
3.寬依賴和窄依賴關係圖:
![](http://static.javashuo.com/static/loading.gif)
3.爲何要有寬窄依賴?
1.前面已經說過了stage劃分的一個很重要的緣由就是有沒有涉及到shuffle,若是沒涉及到的被劃分到一個stage裏面。
2.沒有涉及shuffle的任務直接運行就能夠,這個也就是常提到的pipeline。這種面向的就是窄依賴。
√ 每一個分區裏的數據都被加載到機器的內存裏,咱們逐一的調用 map, filter, map 函數到這些分區裏,Job 就很好的完成。
√ 更重要的是,因爲數據沒有轉移到別的機器,咱們避免了 Network IO 或者 Disk IO.
惟一的任務就是把 map / filter 的運行環境搬到這些機器上運行,這對現代計算機來講,overhead 幾乎能夠忽略不計。
√ 這種把多個操做合併到一塊兒,在數據上一口氣運行的方法在 Spark 裏叫 pipeline
(其實 pipeline 被普遍應用的不少領域,好比 CPU)。
這時候不一樣就出現了:只有 narrow transformation 才能夠進行 pipleline 操做。
對於 wide transformation, RDD 轉換須要不少分區運算,包括數據在機器間搬動,因此失去了 pipeline 的前提。
√ 總結起來一句話:數據和算是否在一塊兒,計算的性能是不同的,爲了區分,就有了寬依賴和窄依賴。
3.一提到shuffle若是以前對mapreduce有過了解的人都知道,這個對分佈式影響巨大,
spark也是一步步演變過來的,如今能夠說spark2.x以上的shuffle能夠認爲和經典的mapreduce的shuffle同樣了,到如今能夠
說spark徹底比mr有優點了。這以前,在一些場景下spark仍是比不過mr的。(看這篇《Spark 與MapReduce 資源調度方面的簡單對比》)
4.寬窄依賴如何優化?----得想一想
4.窄依賴對優化的幫助
1.寬依賴每每對應着shuffle操做,須要在運行過程當中將同一個父RDD的分區傳入到不一樣的子RDD分區中,中間可能涉及到多個節點之間的
數據傳輸;而窄依賴的每一個父RDD的分區只會傳入到一個子RDD分區中,一般能夠在一個節點內就能夠完成了。
2.當RDD分區丟失時(某個節點故障),spark會對數據進行重算。
1).對於窄依賴,因爲父RDD的一個分區只對應一個子RDD分區,這樣只須要重算和子RDD分區對應的父RDD分區便可,
因此這個重算對數據的利用率是100%的;
2).對於寬依賴,重算的父RDD分區對應多個子RDD分區,這樣實際上父RDD 中只有一部分的數據是被用於恢復這個丟失的子RDD
分區的,另外一部分對應子RDD的其它未丟失分區,這就形成了多餘的計算;更通常的,寬依賴中子RDD分區一般來自多個父RDD
分區,極端狀況下,全部的父RDD分區都要進行從新計算。
3.以下圖所示,b1分區丟失,則須要從新計算a1,a2和a3,這就產生了冗餘計算(a1,a2,a3中對應b2的數據)
![](http://static.javashuo.com/static/loading.gif)
區分這兩種依賴頗有用。首先,窄依賴容許在一個集羣節點上以流水線的方式(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