Flink Checkpoint & Savepoint

Checkpoint是Flink實現容錯機制最核心的功能,能夠根據配置週期性地基於Stream中各個Operator的狀態來生成Snapshot,從而將這些狀態數據定期持久化存儲下來,從而將這些狀態數據定期持久化存儲下來,當Flink程序一旦意外崩潰時,重新運行程序時可以有選擇地從這些Snapshot進行恢復,從而修正因爲故障帶來的程序數據狀態中斷。

  1. Checkpoint指定觸發生成時間間隔後,每當需要觸發Checkpoint時,會向Flink程序運行時的多個分佈式的Stream Source中插入一個Barrier標記
  2. 當一個Operator接收到一個Barrier時,它會暫停處理Steam中新接收到的數據記錄
  3. 每個Stream中都會存在對應的Barrier,該Operator要等到所有的輸入Stream中的Barrier都到達。當所有Stream中的Barrier都已經到達該Operator,這時所有的Barrier在時間上看來是同一個時刻點(表示已經對齊)
  4. 該Operator會將數據記錄(Outgoing Records)發射(Emit)出去,作爲下游Operator的輸入
  5. 最後將Barrier對應Snapshot發射(Emit)出去作爲此次Checkpoint的結果數據

開啓checkpoint

val env = StreamExecutionEnvironment.getExecutionEnvironment
    env.setStateBackend(new FsStateBackend("hdfs://ip:8020/flink/flink-checkpoints"))
    val config = env.getCheckpointConfig
    config.enableExternalizedCheckpoints(ExternalizedCheckpointCleanup.RETAIN_ON_CANCELLATION)
    config.setCheckpointingMode(CheckpointingMode.EXACTLY_ONCE)
    config.setCheckpointInterval(60000)

ExternalizedCheckpointCleanup.RETAIN_ON_CANCELLATION,表示一旦Flink處理程序被cancel後,會保留Checkpoint數據,以便根據實際需要恢復到指定的Checkpoint處理。

上面代碼配置了執行Checkpointing的時間間隔爲1分鐘。

保存多個checkpoint

默認情況下,如果設置了Checkpoint選項,則Flink只保留最近成功生成的1個Checkpoint

Flink可以支持保留多個Checkpoint,需要在Flink的配置文件conf/flink-conf.yaml中,添加如下配置,指定最多需要保存Checkpoint的個數:

state.checkpoints.num-retained: 20

如果希望會退到某個Checkpoint點,只需要指定對應的某個Checkpoint路徑即可實現。

從checkpoint 恢復

如果Flink程序異常失敗,或者最近一段時間內數據處理錯誤,我們可以將程序從某一個Checkpoint點,比如chk-860進行回放,執行如下命令

bin/flink run -s hdfs://namenode01.td.com/flink-1.5.3/flink-checkpoints/582e17d2cc343e6c56255d111bae0191/chk-860/_metadata flink-app-jobs.jar
  • 所有的Checkpoint文件都在以Job ID爲名稱的目錄裏面

  • 當Job停掉後,重新從某個Checkpoint點(chk-860)進行恢復時,重新生成Job ID

  • Checkpoint編號會從該次運行基於的編號繼續連續生成:chk-861、chk-862、chk-863

checkpoint的建議

  • Checkpoint 間隔不要太短
    • 過短的間對於底層分佈式文件系統而言,會帶來很大的壓力。
    • Flink 作業處理 record 與執行 checkpoint 存在互斥鎖,過於頻繁的checkpoint,可能會影響整體的性能。
  • 合理設置超時時間

Savepoint會在Flink Job之外存儲自包含(self-contained)結構的Checkpoint,它使用Flink的Checkpointing機制來創建一個非增量的Snapshot,裏面包含Streaming程序的狀態,並將Checkpoint的數據存儲到外部存儲系統中

Flink程序中包含兩種狀態數據:

  • 用戶定義的狀態(User-defined State)是基於Flink的Transformation函數來創建或者修改得到的狀態數據

  • 系統狀態(System State),是指作爲Operator計算一部分的數據Buffer等狀態數據,比如在使用Window Function時,在Window內部緩存Streaming數據記錄

Flink提供了API來爲程序中每個Operator設置ID,這樣可以在後續更新/升級程序的時候,可以在Savepoint數據中基於Operator ID來與對應的狀態信息進行匹配,從而實現恢復。

設置Operator ID:

DataStream<String> stream = env.
  // Stateful source (e.g. Kafka) with ID
  .addSource(new StatefulSource())
  .uid("source-id") // ID for the source operator
  .shuffle()
  // Stateful mapper with ID
  .map(new StatefulMapper())
  .uid("mapper-id") // ID for the mapper
  // Stateless printing sink
  .print(); // Auto-generated ID

創建Savepoint

創建一個Savepoint,需要指定對應Savepoint目錄,有兩種方式來指定

  1. 需要配置Savepoint的默認路徑,需要在Flink的配置文件conf/flink-conf.yaml中,添加如下配置,設置Savepoint存儲目錄
state.savepoints.dir: hdfs://namenode01.td.com/flink/flink-savepoints
  1. 手動執行savepoint命令的時候,指定Savepoint存儲目錄
bin/flink savepoint :jobId [:targetDirectory]

使用默認配置

bin/flink savepoint 40dcc6d2ba90f13930abce295de8d038

爲正在運行的Flink Job指定一個目錄存儲Savepoint數據

bin/flink savepoint 40dcc6d2ba90f13930abce295de8d038 hdfs://namenode01.td.com/tmp/flink/savepoints

從Savepoint恢復

bin/flink run -s :savepointPath [:runArgs]

以上面保存的Savepoint爲例,恢復Job運行

bin/flink run -s hdfs://namenode01.td.com/tmp/flink/savepoints/savepoint-40dcc6-a90008f0f82f flink-app-jobs.jar

會啓動一個新的Flink Job,ID爲cdbae3af1b7441839e7c03bab0d0eefd

Savepoint 目錄結構

OoDSh9.png

  • 1bbc5是Flink Job ID字符串前6個字符,後面bd967f90709b是隨機生成的字符串

  • _metadata文件包含了Savepoint的元數據信息

  • 其他文件內容都是序列化的狀態信息

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章