Spark_Spark中RDD介紹

今天面試被問到了這個問題,感覺自己回答的並不好。寫一下這篇文章記錄一下:

https://www.jianshu.com/p/6411fff954cf

 

Spark基本概念

RDD:彈性分佈式數據集 (Resilient Distributed DataSet)。

Spark 是數據不動,代碼動的架構!!!!

 

RDD 的基本特性

RDD 有三個基本特性 : 分區,不可變,並行操作

 

分區

      每一個 RDD 包含的數據被存儲在系統的不同節點上。邏輯上我們可以將 RDD 理解成一個大的數組,數組中的每個元素就代表一個分區 (Partition) 。

    在物理存儲中,每個分區指向一個存儲在內存或者硬盤中的數據塊 (Block) ,其實這個數據塊就是每個 task 計算出的數據塊,它們可以分佈在不同的節點上。

    所以,RDD 只是抽象意義的數據集合,分區內部並不會存儲具體的數據,只會存儲它在該 RDD 中的 index,通過該 RDD 的 ID 和分區的 index 可以唯一確定對應數據塊的編號,然後通過底層存儲層的接口提取到數據進行處理。

    在集羣中,各個節點上的數據塊會盡可能的存儲在內存中,只有當內存沒有空間時纔會放入硬盤存儲,這樣可以最大化的減少硬盤 IO 的開銷。

 

不可變

     不可變性是指每個 RDD 都是隻讀的,它所包含的分區信息是不可變的。由於已有的 RDD 是不可變的,所以我們只有對現有的 RDD 進行轉化 (Transformation) 操作,才能得到新的 RDD ,一步一步的計算出我們想要的結果。

     這樣會帶來這樣的好處:我們在 RDD 的計算過程中,不需要立刻去存儲計算出的數據本身,我們只要記錄每個 RDD 是經過哪些轉化操作得來的,即:依賴關係,這樣一方面可以提高計算效率,一方面是錯誤恢復會更加容易。如果在計算過程中,第 N 步輸出的 RDD 的節點發生故障,數據丟失,那麼可以根據依賴關係從第 N-1 步去重新計算出該 RDD,這也是 RDD 叫做"彈性"分佈式數據集的一個原因。

 

並行操作

       因爲 RDD 的分區特性,所以其天然支持並行處理的特性。即不同節點上的數據可以分別被處理,然後生成一個新的 RDD。

 

======================================================

 

RDD 的結構

     每個 RDD 裏都會包括分區信息、依賴關係等等的信息,如下圖所示:

 

 

Partitions

   Partitions 就是上面所說的,代表着 RDD 中數據的邏輯結構,每個 Partion 會映射到某個節點內存或者硬盤的一個數據塊。

 

SparkContext

   SparkContext 是所有 Spark 功能的入口,代表了與 Spark 節點的連接,可以用來創建 RDD 對象以及在節點中的廣播變量等等。一個線程只有一個 SparkContext。

 

SparkConf

   SparkConf 是一些配置信息。

 

Partitioner

     Partitioner 決定了 RDD 的分區方式,目前兩種主流的分區方式Hash partioner Range partitioner。Hash 就是對數據的 Key 進行散列分佈,Rang 是按照 Key 的排序進行的分區。也可以自定義 Partitioner。

 

Dependencies

    Dependencies 也就是依賴關係,記錄了該 RDD 的計算過程,也就是說這個 RDD 是通過哪個 RDD 經過怎麼樣的轉化操作得到的。

這裏有個概念,根據每個 RDD 的分區計算後生成的新的 RDD 的分區的對應關係,可以分成窄依賴和寬依賴。

窄依賴就是父 RDD 的分區可以一一對應到子 RDD 的分區,寬依賴是說父 RDD 的每個分區可以被多個子 RDD 分區使用。如圖:

    由於窄依賴的特性,窄依賴允許子 RDD 的每個分區可以被並行處理產生,而且支持在同一個節點上鍊式執行多條指令,無需等待其它父 RDD 的分區操作。

Spark 區分寬窄依賴的原因主要有兩點:

  • 窄依賴支持在同一節點上進行鏈式操作,比如在執行了 map 後,緊接着執行 filter 操作。相反,款依賴需要所有父分區都是可用的。
  • 從失敗恢復的角度考慮,窄依賴失敗恢復更有效,因爲只要重新計算丟失的父分區即可,而寬依賴涉及到 RDD 的各級多個父分區。

 

Checkpoint

     檢查點機制,在計算過程中有一些比較耗時的 RDD,我們可以將它緩存到硬盤或者 HDFS 中,標記這個 RDD 有被檢查點處理過,並且清空它的所有依賴關係。同時,給它新建一個依賴於 CheckpointRDD 的依賴關係,CheckpintRDD 可以用來從 硬盤中讀取 RDD 和生成新的分區信息。

    這麼做之後,當某個 RDD 需要錯誤恢復時,回溯到該 RDD,發現它被檢查點記錄過,就可以直接去硬盤讀取該 RDD,無需重新計算。
 

 

Preferred Location

   針對每一個分片,都會選擇一個最優的位置來計算,數據不動代碼動

 

Storage Level

用來記錄 RDD 持久化時存儲的級別,常用的有:

  • MEMORY_ONLY:只存在緩存中,如果內存不夠,則不緩存剩餘的部分。這是 RDD 默認的存儲級別。
  • MEMORY_AND_DISK:緩存在內存中,不夠則緩存至內存。
  • DISK_ONLY:只存硬盤。
  • MEMORY_ONLY_2 和 MEMORY_AND_DISK_2等:與上面的級別和功能相同,只不過每個分區在集羣兩個節點上建立副本。

 

Iterator

   迭代函數和計算函數是用來表示 RDD 怎樣通過父 RDD 計算得到的。

   迭代函數首先會判斷緩存中是否有想要計算的 RDD,如果有就直接讀取,如果沒有就查找想要計算的 RDD 是否被檢查點處理過。如果有,就直接讀取,如果沒有,就調用計算函數向上遞歸,查找父 RDD 進行計算。



 

 

 

 

 

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