RDD-Dependency講解

概要

上一篇我們介紹了代表RDD組成的(Dependency、Partition、Partitioner)之一的Partition,這篇接着介紹Dependency。Partition記錄的是數據split的邏輯,Dependency記錄的是transformation操作過程中Partition的演化,即這個Partition從哪來到哪去的過程,以及通過Dependency的類型判斷如何處理數據,即pipeline還是shuffle。

Dependency定義

 
先看下Dependency的定義: 

Dependency是抽象類,有一個屬性rdd,就是對應RDD的父RDD,所以Dependency就是對父RDD的包裝,並且通過Dependency的類型說明當前這個transformation對應的數據處理方式,其主要子類實現,即Dependency的類型有兩大類:

  • ##NarrowDependency(窄依賴) 

    窄依賴依然是抽象類,繼承了rdd,並在定義中增加抽象方法getParents,根據子RDD的PartitionId返回對應的父RDD的PartitionId,接下來查看窄依賴的具體實現: 
    1. OneToOneDependency 

      OneToOneDependency表示子RDD和父RDD的Partition之間的關係是1對1的,即子RDD的PartitionId和父RDD的PartitionId一樣,如第一幅圖中,Narrow Dependency下面的map和filter方法所示的關係。
    2. RangeDependency RangeDependency表示子RDD和父RDD的Partition之間的關係是一個區間內的1對1對應關係,第一幅圖中所示Narrow Dependency下面的union就是RangeDependency
    3. PruneDependency 子RDD的Partition來自父RDD的多個Partition,filterByRange方法時會使用,不做詳細討論
  • ##ShuffleDependency(寬依賴) 
  • ShuffleDependency的定義相對複雜一些,因爲shuffle設計到網絡傳輸,所以要有序列化serializer,爲了減少網絡傳輸,可以加map端聚合,通過mapSideCombine和aggregator控制,還有key排序相關的keyOrdering,以及重輸出的數據如何分區的partitioner,其他信息包括k,v和combiner的class信息以及shuffleId。shuffle是個相對複雜且開銷大的過程,Partition之間的關係在shuffle處戛然而止,因此shuffle是劃分stage的依據。

Dependency分爲兩大類,寬依賴和窄依賴,窄依賴有兩個主要實現。

舉個例子

以Wordcount爲例

 

val wordcount = sc.parallelize(List("a c", "a b")) wordcount.flatMap(_.split(" ")).map((_, 1)).reduceByKey(_ + _).collect() wordcount = sc.parallelize(List("a c", "a b")) wordcount.flatMap(_.split(" ")).map((_, 1)).reduceByKey(_ + _).collect()

通過web UI查看DAG,如下: 
 
可以看出,其根據shuffle的位置劃分爲兩個stage,stage0和stage1 
調用toDebugString查看各RDD之間關係 

最後,總結出Wordcount中RDD及其對應的Dependency如下,其中方形代表RDD,圓角矩形代表Partition(3個圓角矩形是爲了作圖方便,不代表其具體有3個Partition),文本框內第一行爲代碼片段,第二行是對應的RDD,第三行爲RDD的Dependency類型 

總結

Dependency是RDD的重要組成,分爲寬依賴和窄依賴兩大類,實質就是其父RDD的包裝,由Dependency組成的關係構成了lineage的物理結構,也是DAG的物理結構,寬依賴(即shuffle操作)是stage劃分的依據,窄依賴可以執行流水線(pipeline)操作,效率高。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章