源碼解釋
/** *Mark this RDD for checkpointing. It will be saved to a file inside the checkpoint 將此RDD標記為檢查點。它將保存到檢查點內的文件中 *directory set with `SparkContext#setCheckpointDir` and all references to its parent 使用“SparkContext”setCheckpointDir設置的目錄及其對其父目錄的所有引用 *RDDs will be removed. This function must be called before any job has been RDD將被刪除。必須在調用任何作業之前調用此函數 *executed on this RDD. It is strongly recommended that this RDD is persisted in emory, otherwise saving it on a file will require recomputation. 對於這個RDD執行時,烈建議先在內存緩存,否則將其保存在文件中需要重新計算。 */
- Spark 中對於數據的保存除了持久化操作之外,還提供了一種檢查點的機制,檢查點(本質是通過將RDD寫入Disk做檢查點)是為了通過 Lineage 做容錯的輔助
- Lineage 過長會造成容錯成本過高,這樣就不如在中間階段做檢查點容錯,如果之后有節點出現問題而丟失分區,從做檢查點的 RDD 開始重做 Lineage,就會減少開銷。
- 檢查點通過將數據寫入到 HDFS 文件系統實現了 RDD 的檢查點功能。
- 為當前 RDD 設置檢查點。該函數將會創建一個二進制的文件,並存儲到 checkpoint 目錄中,該目錄是用 SparkContext.setCheckpointDir()設置的。在 checkpoint 的過程中,該RDD 的所有依賴於父 RDD中 的信息將全部被移除。
- 對 RDD 進行 checkpoint 操作並不會馬上被執行,必須執行 Action 操作才能觸發, 在觸發的時候需要對這個 RDD 進行計算.
為什么建議在 checkpoint前先緩存?
executed on this RDD. It is strongly recommended that this RDD is persisted in emory, otherwise saving it on a file will require recomputation
源碼已經說明,如果不緩存,在真正執行保存操作時,spark還會計算一次(安全起見),如果設置了緩存則不會重復計算。
重復計算不僅浪費性能,如果算子中包含當前時間,顯然兩次計算結果時間是不一樣的。即持久化的時間跟第一次計算時的時間不一樣。
持久化和checkpoint的區別
- 持久化只是將數據保存在 BlockManager 中,而 RDD 的 Lineage 是不變的。但是checkpoint 執行完后,RDD 已經沒有之前所謂的依賴 RDD 了,而只有一個強行為其設置的checkpointRDD,RDD 的 Lineage 改變了。
- 持久化的數據丟失可能性更大,磁盤、內存都可能會存在數據丟失的情況。但是 checkpoint 的數據通常是存儲在如 HDFS 等容錯、高可用的文件系統,數據丟失可能性較小。
- 注意: 默認情況下,如果某個 RDD 沒有持久化,但是設置了checkpoint,會存在問題. 本來這個 job 都執行結束了,但是由於中間 RDD 沒有持久化,checkpoint job 想要將 RDD 的數據寫入外部文件系統的話,需要全部重新計算一次,再將計算出來的 RDD 數據 checkpoint到外部文件系統。 所以,建議對 checkpoint()的 RDD 使用持久化, 這樣 RDD 只需要計算一次就可以了.