深入理解RDD

  •    RDD最基本的五個特徵

        RDD 即 Resilient Distributes Dataset, 是spark中最基礎、最常用的數據結構。其本質是把input source 進行封裝,封裝之後的數據結構就是RDD,提供了一系列操作,比如 map、flatMap、filter等。input source種類繁多,比如hdfs上存儲的文件、本地存儲的文件,相應的 RDD的種類也有很多。不同的input source 對應着不同的rdd 類型。比如從hdfs上讀取的text對應着HadoopRDD, val hRdd= sc.textFile(“hfs://…….”) 生成的就是HadoopRDD。



  如圖所示,RDD是一個父類,是一個抽象類,封裝了rdd的基本屬性和常用操作。每一個具體的子類rdd都繼承了該父類。

  rdd包含五個特徵:
  1. 一個分片列表 partition list
  2. 一個計算函數compute,對每一個split進行計算
  3. 對其他rdd的依賴列表dependencies list.依賴又份 寬依賴和窄依賴。
  4. partitioner for key-value RDDs.比如說 hash-partitioned rdd(這是可選的,並不是所有的add都會有這個特徵)
  5. 對每一個split計算的優先位置 Preferred Location。比如對一個hdfs文件進行計算時,可以獲取優先計算的block locations
  以上五個特徵中包含四個函數和一個屬性,如下所示:
  1. protected def getPartitions: Array[Partition]     //only called once
  2. def compute(split: Partition, context: TaskContext): Iterator[T]
  3. protected def getDependencies: Seq[Dependency[_]] = dips    //only called once
  4. protected def getPreferredLocations(split: Partition): Seq[String] = Nil
  5. @transient val partitioner: Option[Partitioner] = None
    這五個特徵的定義包含在抽象父類RDD中(對應於上圖中的RDD,具體的代碼在RDD.scala中),每一個具體類型的rdd子類繼承RDD父類之後都會部分或全部override這五個特徵。如MapPartitionsRDD就重寫了其中的三個:
  • override val partitioner if (preservesPartitioning) firstParent[T].partitioner else None
  • override def getPartitions: Array[Partition] = firstParent[T].partitions
  • override def compute(split: Partition, context: TaskContext): Iterator[U] = f(context, split.index, firstParent[T].iterator(split, context))


  • RDD structure
      抽象父類RDD的結構如下:

      
                                     <注: 圖中列出的是主要屬性和方法>
  如上圖所示,每一個rdd都有一個id,這個id是調用sparkcontext中的函數生成的:
 
  /** A unique ID for this RDD (within its SparkContext). */
  val id: Int = sc.newRddId()
 而newRddId()最終調用的是AtmoicInteger.java中類AtomicInteger的getAndIncrement()方法。在常用的方法中,persist()是一個持久化函數,調用該函數要設置
storageLevel,常見的設置有MEMORY_ONLY(這是默認值),MEMOEY_AND_DISK,以及DISK_ONLY。checkpoint()方法會把當前rdd保存到一個目錄中,該目錄是調用sparkcontext中的
setCheckpointDir()方法生成的。checkpoint的時候,會把所有依賴的父級rdd信息清除掉。注意,checkpoint不會馬上執行,要觸發action操作的時候纔會執行。
因爲 checkpoint會清除父級rdd的信息,所以在做checkpoint應該先做persist操作,否則就要重新計算一遍。checkpoint的好處顯而易見,比如做1000次迭代,在
第999次時做了checkpoint,如果第1000次的時候,只要重新計算第1000即可,不用從頭到尾再計算一次。
   rdd中有兩種算子:
  • Transformation: 返回一個新rdd,可以對返回的rdd繼續做transformation操作。因爲一個rdd的不同分區可以存在不同節點上,所以transformation是可以
   並行的,一個task對應一個rdd的塊。另外,transformation 操作是lazy的,不會馬上執行,只有觸發了Action算子時纔會執行。
  • Action: 返回值不是rdd,返回值是一個集合、值或者返回爲空。返回的結果要麼傳給driver,要麼保存到文件系統。
   以下是常有的算子:
   

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