轉載於“牛肉圓粉不加蔥”
連結:http://www.jianshu.com/p/00b591c5f623
一個 Streaming Application 往往需要7*24不間斷的跑,所以需要有抵禦意外的能力(比如機器或者系統掛掉,JVM crash等)。為了讓這成為可能,Spark Streaming需要 checkpoint 足夠多資訊至一個具有容錯設計的儲存系統才能讓 Application 從失敗中恢複。Spark Streaming 會 checkpoint 兩種類型的資料。
Metadata(中繼資料) checkpointing - 儲存定義了 Streaming 計算邏輯至類似 HDFS 的支援容錯的儲存系統。用來恢複 driver,中繼資料套件括: 配置 - 用於建立該 streaming application 的所有配置 DStream 操作 - DStream 一些列的操作 未完成的 batches - 那些提交了 job 但尚未執行或未完成的 batches
Data checkpointing - 儲存已產生的RDDs至可靠的儲存。這在某些 stateful 轉換中是需要的,在這種轉換中,產生 RDD 需要依賴前面的 batches,會導致依賴鏈隨著時間而變長。為了避免這種沒有盡頭的變長,要定期將中間產生的 RDDs 儲存到可靠儲存來切斷依賴鏈
總之,metadata checkpointing 主要用來恢複 driver;而 RDD資料的 checkpointing 對於stateful 轉換操作是必要的。 什麼時候需要啟用 checkpoint。
什麼時候該啟用 checkpoint 呢。滿足以下任一條件: 使用了 stateful 轉換 - 如果 application 中使用了updateStateByKey或reduceByKeyAndWindow等 stateful 操作,必須提供 checkpoint 目錄來允許定時的 RDD checkpoint 希望能從意外中恢複 driver
如果 streaming app 沒有 stateful 操作,也允許 driver 掛掉後再次重啟的進度丟失,就沒有啟用 checkpoint的必要了。 如何使用 checkpoint。
啟用 checkpoint,需要設定一個支援容錯 的、可靠的檔案系統(如 HDFS、s3 等)目錄來儲存 checkpoint 資料。通過調用 streamingContext.checkpoint(checkpointDirectory) 來完成。另外,如果你想讓你的 application 能從 driver 失敗中恢複,你的 application 要滿足: 若 application 為首次重啟,將建立一個新的 StreamContext 執行個體 如果 application 是從失敗中重啟,將會從 checkpoint 目錄匯入 checkpoint 資料來重新建立 StreamingContext 執行個體
通過 StreamingContext.getOrCreate 可以達到目的:
// Function to create and setup a new StreamingContextdef functionToCreateContext(): StreamingContext = { val ssc = new StreamingContext(...) // new context val lines = ssc.socketTextStream(...) // create DStreams ... ssc.checkpoint(checkpointDirectory) // set checkpoint directory ssc}// Get StreamingContext from checkpoint data or create a new oneval context = StreamingContext.getOrCreate(checkpointDirectory, functionToCreateContext _)// Do additional setup on context that needs to be done,// irrespective of whether it is being started or restartedcontext. ...// Start the contextcontext.start()context.awaitTermination()
如果 checkpointDirectory 存在,那麼 context 將匯入 checkpoint 資料。如果目錄不存在,函數 functionToCreateContext 將被調用並建立新的 context
除調用 getOrCreate 外,還需要你的叢集模式支援 driver 掛掉之後重啟之。例如,在 yarn 模式下,driver 是運行在 ApplicationMaster 中,若 ApplicationMaster 掛掉,yarn 會自動在另一個節點上啟動一個新的 ApplicationMaster。
需要注意的是,隨著 streaming application 的持續運行,checkpoint 資料佔用的儲存空間會不斷變大。因此,需要小心設定checkpoint 的時間間隔。設定得越小,checkpoint 次數會越多,佔用空間會越大;如果設定越大,會導致恢複時丟失的資料和進度越多。一般推薦設定為 batch duration 的5~10倍。 匯出 checkpoint 資料
上文提到,checkpoint 資料會定時匯出到可靠的儲存系統,那麼
在什麼時機進行 checkpoint
checkpoint 的形式是怎麼樣的 checkpoint 的時機
在 Spark Streaming 中,JobGenerator 用於產生每個 batch 對應的 jobs,它有一個定時器,定時器的周期即初始化 StreamingContext 時設定的 batchDuration。這個周期一到,JobGenerator 將調用generateJobs方法來產生並提交 jobs,這之後調用 doCheckpoint 方法來進行 checkpoint。doCheckpoint 方法中,會判斷目前時間與 streaming application start 的時間之差是否是 checkpoint duration 的倍數,只有在是的情況下才進行 checkpoint。 checkpoint 的形式
最終 checkpoint 的形式是將類 Checkpoint的執行個體序列化後寫入外部儲存,值得一提的是,有專門的一條線程來做將序列化後的 checkpoint 寫入外部儲存。類 Checkpoint 包含以下資料
除了 Checkpoint 類,還有 CheckpointWriter 類用來匯出 checkpoint,CheckpointReader 用來匯入 checkpoint。 Checkpoint 的局限
Spark Streaming 的 checkpoint 機制看起來很美好,卻有一個硬傷。上文提到最終刷到外部儲存的是類 Checkpoint 對象序列化後的資料。那麼在 Spark Streaming application 重新編譯後,再去還原序列化 checkpoint 資料就會失敗。這個時候就必須建立 StreamingContext。
針對這種情況,在我們結合 Spark Streaming + kafka 的應用中,我們自我維護了消費的 offsets,這樣一來及時重新編譯 application,還是可以從需要的 offsets 來消費資料,這裡只是舉個例子,不詳細展開了。