《Spark Streaming實時流式大數據處理實戰》 ——3.6 RDD持久化(Cachinng/Persistence
3.6? RDD持久化(Cachinng/Persistence)
前面幾節介紹了RDD的各種細節,本節將介紹Spark賦予RDD的另一個特性,即持久化(Persisting/Cache)。這個概念其實很好理解,我們在前文中介紹過RDD通過轉換操作(Transformation)會形成有向無環圖,之后Action操作會激活真實的計算。
如果我們持久化一個RDD,其每個節點的各個分支(partition)會將計算結果保存在內存中,并可以將其用在其他Action操作中,也就是說我們只需計算一次RDD,在將來有Action操作需要再次用到該RDD的時候,速度會更加快(通常超過10倍)。將RDD持久化在迭代算法和快速交互場景中可以起到關鍵作用。
我們可以通過rdd.persist()或者rdd.cache()方法將一個RDD標記為持久化,一旦一個RDD通過Action操作激活計算后,其就會保存在節點的內存中。并且Spark的緩存機制是有容錯性的,即如果一個RDD的某個分支(Partition)丟失,它會自動根據之前創建的轉換操作重新計算。
此外,可以使用不同的存儲級別(storage level)對RDD進行持久化,在節點之間復制。例如,可以將一個數據集持久化在硬盤或者內存,就像Java當中對對象的序列化(serialized)一樣。在調用persist方法時,我們可以傳遞存儲級別參數來進行設置,而cache方法會使用默認的存儲級別StorageLevel.MEMORY_ONLY(在內存中保存和反序列化對象)。所有的存儲級別如表3.2所示。
表3.2? RDD持久化的不同存儲級別
以序列化的格式存儲RDD到離線堆內存中(OFF_HEAP Memory),要求OFF_HEAP Memory是可用的。相對于MEMORY_ONLY_SER,OFF_HEAP減少了垃圾回收的花費,允許更小的執行者共享內存池。這使其在擁有大量內存的環境下或者多并發應用程序的環境中具有更強的吸引力
?注意:當通過Python使用Spark時,所有需要存儲的對象都會由Pickle庫來完成序列化,所以對于Python版本序列化級別(serialized level)是無關緊要的。Python中可選擇的存儲級別(storage level)包括:MEMORY_ONLY、MEMORY_ONLY_2、MEMORY_AND_DISK、MEMORY_AND_DISK_2、DISK_ONLY和 DISK_ONLY_2。
另外,即使用戶沒有調用persist函數,Spark也會自動將Shuffle操作的一些中間數據進行持久化(如reduceByKey)。這主要是為了防止在Shuffle操作期間,當一個節點失敗時導致全局的重新計算。對于需要反復使用的RDD結果,最好利用persist操作將其持久化,從而避免重復計算。
關于如何選擇存儲級別,需要權衡內存消耗和CPU效率,主要從以下幾點來考慮:
* 如果在默認的存儲級別(MEMORY_ONLY)滿足要求的情況下,就不要切換,因為這是CPU的最高效形式,可以使得RDD操作盡可能地快速執行。
* 如果不能滿足要求,那么嘗試MEMORY_ONLY_SER,并且選取一個高效的序列化庫使得對象能夠在空間合理、高效訪問的前提下被序列化(只能在Java和Scala中使用)。
* 除非計算RDD的花費較大或者它們需要過濾大量的數據,不要將RDD存儲到磁盤上(DISK),否則,重復計算一個分區就和從磁盤上讀取數據一樣慢。
* 如果希望更快的錯誤恢復(如將Spark用來服務一個Web應用的請求),可以利用重復(replicated)存儲級別。所有的存儲級別都可以通過重復計算丟失的數據來支持完整的容錯,但是重復的數據能夠使我們在RDD上繼續運行任務,而不需要重復計算丟失的數據。
Spark會自動監視每個節點的緩存使用情況,并且根據最近最久未使用(LRU least-recently-used)原則來刪除舊的數據分支。如果希望手動將RDD從緩存中移除,可以使用RDD.unpersist方法。
Spark spark 大數據 大數據
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。