緩存
緩存概述
如果在應用程序中多次使用同一個 RDD,可以將該 RDD 緩存在計算節點的內存中,該 RDD 只有在第一次計算的時候會根據血緣關係得到分區的數據,在後續其他地方用到該 RDD 的時候,會直接從緩存處取而不用再根據血緣關係計算,這樣就加速後期的重用。在使用完數據之後,要釋放緩存,否則會一直在內存中佔用資源。
cache在執行的時候也是 lazy 的,需要一個action觸發;
但是去除緩存時是eagle的;
cache如果採用默認的機制,數據緩存以後,佔的內存會變大
什麼時候需要緩存:
- 要求的計算速度快,對效率要求高的時候
- 集羣的資源要足夠大,能容得下要被緩存的數據(緩存需要佔用內存)
- 被緩存的數據會多次的觸發Action(多次調用Action類的算子)
- 先進行過濾,然後將縮小範圍後的數據緩存到內存中
cache()和persist()區別
cache:以默認的存儲級別持久化存儲RDD (MEMORY_ONLY)
def cache():this.type = persist()
persist:
def persist():this.type=persist(StorageLevel.MEMORY_ONLY)
/*StorageLevel : 存儲級別
StorageLevel中的屬性:
_useDisk: 是否使用磁盤
_useMemory: 是否使用內存
_useOffHeap: 是否使用堆外內存
_deserialized: 是否反序列化
_replication: 副本個數*/
cache() 調用 persist()
core 的 cache() 採用的默認存儲級別是 :
不使用硬盤,使用內存,不使用堆外,支持反序列化,1副本
在生產上使用:MEMORY_ONLY/MEMORY_ONLY_SER
默認存儲使用 MEMORY_ONLY是最好的
如果CPU性能OK,可以使用 MEMORY_ONLY_SER
使用這兩者存儲級別的原因是:
- 生產上爲了保證速度,存儲級別裏只要帶DISK的都不要選擇,存到DISK裏還不如recomputing,所以是不會將緩存的放在 disk 中 ;
- Spark本身就有一定的容錯機制,所以沒有必要使用多副本。
CheckPoint
雖然 RDD 的血緣關係天然地可以實現容錯,當 RDD 的某個分區數據失敗或丟失,可以通過血緣關係重建。但是對於長時間迭代型應用來說,隨着迭代的進行, RDDs 之間的血緣關係會越來越長,一旦在後續迭代過程中出錯,則需要通過非常長的血緣關係去重建,勢必影響性能。爲此, RDD 支持 checkpoint 將數據保存到持久化的存儲中,這樣就可以切斷之前的血緣關係,因爲 checkpoint後的RDD 不需要知道它的父RDDs 了,它可以從 checkpoint處拿到數據。
設置checkpoint的目錄,可以是本地的文件夾、也可以是HDFS。一般是在具有容錯能力,高可靠的文件系統上(比如HDFS, S3等)設置一個檢查點路徑,用於保存檢查點數據。checkPoint減少運行時間的原因:第一次調用檢查點的時候,會產生兩個executor,兩個進程分別是從hdfs讀文件和計算(調用的Action類的算子),在第二次調用的時候會發現,運行的時間大大減少,是由於第二次調用算子的時候,不會再從hdfs讀文件,而讀取的是緩存到的數據,同樣是從hdfs上讀取。