Spark中RDD的高效與DAG(有向無環(huán)圖)有很大的關(guān)系,在DAG調(diào)度中需要對計(jì)算的過程劃分Stage,劃分的依據(jù)就是RDD之間的依賴關(guān)系。RDD之間的依賴關(guān)系分為兩種,寬依賴(wide dependency/shuffle dependency)和窄依賴(narrow dependency)
1.窄依賴
窄依賴就是指父RDD的每個分區(qū)只被一個子RDD分區(qū)使用,子RDD分區(qū)通常只對應(yīng)常數(shù)個父RDD分區(qū),如下圖所示【其中每個小方塊代表一個RDD Partition】
窄依賴.png
窄依賴有分為兩種:
- 一種是一對一的依賴,即OneToOneDependency
- 還有一個是范圍的依賴,即RangeDependency,它僅僅被org.apache.spark.rdd.UnionRDD使用。UnionRDD是把多個RDD合成一個RDD,這些RDD是被拼接而成,即每個parent RDD的Partition的相對順序不會變,只不過每個parent RDD在UnionRDD中的Partition的起始位置不同
2.寬依賴
寬依賴就是指父RDD的每個分區(qū)都有可能被多個子RDD分區(qū)使用,子RDD分區(qū)通常對應(yīng)父RDD所有分區(qū),如下圖所示【其中每個小方塊代表一個RDD Partition】
寬依賴.png
3.窄依賴與窄依賴比較
- 寬依賴往往對應(yīng)著shuffle操作,需要在運(yùn)行的過程中將同一個RDD分區(qū)傳入到不同的RDD分區(qū)中,中間可能涉及到多個節(jié)點(diǎn)之間數(shù)據(jù)的傳輸,而窄依賴的每個父RDD分區(qū)通常只會傳入到另一個子RDD分區(qū),通常在一個節(jié)點(diǎn)內(nèi)完成。
- 當(dāng)RDD分區(qū)丟失時(shí),對于窄依賴來說,由于父RDD的一個分區(qū)只對應(yīng)一個子RDD分區(qū),這樣只需要重新計(jì)算與子RDD分區(qū)對應(yīng)的父RDD分區(qū)就行。這個計(jì)算對數(shù)據(jù)的利用是100%的
- 當(dāng)RDD分區(qū)丟失時(shí),對于寬依賴來說,重算的父RDD分區(qū)只有一部分?jǐn)?shù)據(jù)是對應(yīng)丟失的子RDD分區(qū)的,另一部分就造成了多余的計(jì)算。寬依賴中的子RDD分區(qū)通常來自多個父RDD分區(qū),極端情況下,所有父RDD都有可能重新計(jì)算。如下圖,par4丟失,則需要重新計(jì)算par1,par2,par3,產(chǎn)生了冗余數(shù)據(jù)par5
分區(qū)丟失.png
4.寬依賴,窄依賴函數(shù)
- 窄依賴的函數(shù)有:
map, filter, union, join(父RDD是hash-partitioned ), mapPartitions, mapValues - 寬依賴的函數(shù)有:
groupByKey, join(父RDD不是hash-partitioned ), partitionBy