1. 程式人生 > >Spark效能調優之——在實際專案中重構RDD架構以及RDD持久化

Spark效能調優之——在實際專案中重構RDD架構以及RDD持久化

一、RDD架構重構與優化是什麼。

儘量去複用RDD,差不多的RDD,可以抽取為一個共同的RDD,供後面的RDD計算時,反覆使用。

二、怎麼做?

快取級別:

    case "NONE" => NONE
    case "DISK_ONLY" => DISK_ONLY
    case "DISK_ONLY_2" => DISK_ONLY_2
    case "MEMORY_ONLY" => MEMORY_ONLY
    case "MEMORY_ONLY_2" => MEMORY_ONLY_2
    case "MEMORY_ONLY_SER"
=> MEMORY_ONLY_SER case "MEMORY_ONLY_SER_2" => MEMORY_ONLY_SER_2 case "MEMORY_AND_DISK" => MEMORY_AND_DISK case "MEMORY_AND_DISK_2" => MEMORY_AND_DISK_2 case "MEMORY_AND_DISK_SER" => MEMORY_AND_DISK_SER case "MEMORY_AND_DISK_SER_2" => MEMORY_AND_DISK_SER_2 case
"OFF_HEAP" => OFF_HEAP

使用示例:

sessionid2actionRDD = sessionid2actionRDD.persist(StorageLevel.MEMORY_ONLY());

/** 
cache就是一個特殊的預設在記憶體中的快取。
Persist this RDD with the default storage level (`MEMORY_ONLY`). 
*/
def cache(): JavaPairRDD[K, V] = new JavaPairRDD[K, V](rdd.cache())

三、為什麼需要重構優化RDD?

這裡寫圖片描述

如圖所示。如果rdd沒有快取。
在計算RDD3的時候,會從hdfs讀取一份,到RDD1到RDD2 到RDD3 需要15分鐘。
再需要計算RDD4的時候,會重新從HDFS中讀取,計算, 又需要耗時15分鐘。 那麼總共就需要30分鐘。

如果把RDD1 快取在記憶體或磁碟中。
那麼 要計算的時候,直接從記憶體或磁碟中讀取RDD1 即可,不需要再次讀取HDFS,以及重新計算RDD1. 這樣 總時間 就只需要20分鐘。 大大提升了效率。

四、公共RDD一定要實現持久化。

對於多次計算和公共的RDD,一定要進行持久化。
持久化,也就是說,將RDD的資料快取到記憶體中、磁碟中,BlockManager。
以後無論對這個RDD做多少次計算,那麼都直接取這個RDD的持久化的資料,比如從記憶體中,或者磁碟中,直接提取一份資料。

五、持久化的時候是可以進行序列化的。

如果正常將資料持久化在記憶體中,那麼可能會導致記憶體佔用過大,這樣的話,也許會導致OOM記憶體溢位。

當純記憶體無法支撐公共RDD資料完全存放的時候,就優先考慮,使用序列化的方式,在純記憶體中儲存。
將RDD的每個partion的資料,序列化成一個大的位元組陣列,就一個物件;
序列化後,大大減少記憶體的空間佔用。

序列化的方式,唯一的缺點,就是,獲取資料的時候,需要反序列化。

如果序列化純記憶體的方式,還是導致OOM,記憶體溢位。
就只能考慮磁碟的方式,記憶體+磁碟,普通方式(持久化)
記憶體+磁碟 ,序列化。

六、為了資料的高可靠,而且記憶體充足,可以使用雙副本機制,進行持久化。

持久化雙副本,持久化後的一個副本,因為機器宕機了,副本丟了,就還是得重新計算一次;

持久化的每個資料單元,儲存一份副本,放在其他節點上,從而進行容錯。一個副本丟了,可以使用另外一個。

這種方式,僅僅針對記憶體資源極度充足。!