Flink快照容錯處理

自在现实發表於2024-06-15

透過狀態快照實現容錯處理 #
State Backends #
由 Flink 管理的 keyed state 是一種分片的鍵/值儲存,每個 keyed state 的工作副本都儲存在負責該鍵的 taskmanager 本地中。另外,Operator state 也儲存在機器節點本地。Flink 定期獲取所有狀態的快照,並將這些快照複製到持久化的位置,例如分散式檔案系統。

如果發生故障,Flink 可以恢復應用程式的完整狀態並繼續處理,就如同沒有出現過異常。

Flink 管理的狀態儲存在 state backend 中。Flink 有兩種 state backend 的實現 – 一種基於 RocksDB 內嵌 key/value 儲存將其工作狀態儲存在磁碟上的,另一種基於堆的 state backend,將其工作狀態儲存在 Java 的堆記憶體中。這種基於堆的 state backend 有兩種型別:FsStateBackend,將其狀態快照持久化到分散式檔案系統;MemoryStateBackend,它使用 JobManager 的堆儲存狀態快照。

名稱 Working State 狀態備份 快照
RocksDBStateBackend 本地磁碟(tmp dir) 分散式檔案系統 全量 / 增量
支援大於記憶體大小的狀態
經驗法則:比基於堆的後端慢10倍
FsStateBackend JVM Heap 分散式檔案系統 全量
快速,需要大的堆記憶體
受限制於 GC
MemoryStateBackend JVM Heap JobManager JVM Heap 全量
適用於小狀態(本地)的測試和實驗
當使用基於堆的 state backend 儲存狀態時,訪問和更新涉及在堆上讀寫物件。但是對於儲存在 RocksDBStateBackend 中的物件,訪問和更新涉及序列化和反序列化,所以會有更大的開銷。但 RocksDB 的狀態量僅受本地磁碟大小的限制。還要注意,只有 RocksDBStateBackend 能夠進行增量快照,這對於具有大量變化緩慢狀態的應用程式來說是大有裨益的。

所有這些 state backends 都能夠非同步執行快照,這意味著它們可以在不妨礙正在進行的流處理的情況下執行快照。

Back to top

Checkpoint Storage #
Flink 定期對每個運算元的所有狀態進行持久化快照,並將這些快照複製到更持久的地方,例如分散式檔案系統。 如果發生故障,Flink 可以恢復應用程式的完整狀態並恢復處理,就好像沒有出現任何問題一樣。

這些快照的儲存位置是透過作業_checkpoint storage_定義的。 有兩種可用檢查點儲存實現:一種持久儲存其狀態快照 到一個分散式檔案系統,另一種是使用 JobManager 的堆。

名稱 狀態備份
FileSystemCheckpointStorage 分散式檔案系統
支援非常大的狀態大小
高度可靠
推薦用於生產部署
JobManagerCheckpointStorage JobManager JVM Heap
適合小狀態(本地)的測試和實驗
Back to top

狀態快照 #
定義 #
快照 – 是 Flink 作業狀態全域性一致映象的通用術語。快照包括指向每個資料來源的指標(例如,到檔案或 Kafka 分割槽的偏移量)以及每個作業的有狀態運算子的狀態副本,該狀態副本是處理了 sources 偏移位置之前所有的事件後而生成的狀態。

Checkpoint – 一種由 Flink 自動執行的快照,其目的是能夠從故障中恢復。Checkpoints 可以是增量的,併為快速恢復進行了最佳化。

外部化的 Checkpoint – 通常 checkpoints 不會被使用者操縱。Flink 只保留作業執行時的最近的 n 個 checkpoints(n 可配置),並在作業取消時刪除它們。但你可以將它們配置為保留,在這種情況下,你可以手動從中恢復。

Savepoint – 使用者出於某種操作目的(例如有狀態的重新部署/升級/縮放操作)手動(或 API 呼叫)觸發的快照。Savepoints 始終是完整的,並且已針對操作靈活性進行了最佳化。

狀態快照如何工作? #
Flink 使用 Chandy-Lamport algorithm 演算法的一種變體,稱為非同步 barrier 快照(asynchronous barrier snapshotting)。

當 checkpoint coordinator(job manager 的一部分)指示 task manager 開始 checkpoint 時,它會讓所有 sources 記錄它們的偏移量,並將編號的 checkpoint barriers 插入到它們的流中。這些 barriers 流經 job graph,標註每個 checkpoint 前後的流部分。

Checkpoint barriers are inserted into the streams
Checkpoint n 將包含每個 operator 的 state,這些 state 是對應的 operator 消費了嚴格在 checkpoint barrier n 之前的所有事件,並且不包含在此(checkpoint barrier n)後的任何事件後而生成的狀態。

當 job graph 中的每個 operator 接收到 barriers 時,它就會記錄下其狀態。擁有兩個輸入流的 Operators(例如 CoProcessFunction)會執行 barrier 對齊(barrier alignment) 以便當前快照能夠包含消費兩個輸入流 barrier 之前(但不超過)的所有 events 而產生的狀態。

Barrier alignment
Flink 的 state backends 利用寫時複製(copy-on-write)機制允許當非同步生成舊版本的狀態快照時,能夠不受影響地繼續流處理。只有當快照被持久儲存後,這些舊版本的狀態才會被當做垃圾回收。

確保精確一次(exactly once) #
當流處理應用程式發生錯誤的時候,結果可能會產生丟失或者重複。Flink 根據你為應用程式和叢集的配置,可以產生以下結果:

Flink 不會從快照中進行恢復(at most once)
沒有任何丟失,但是你可能會得到重複冗餘的結果(at least once)
沒有丟失或冗餘重複(exactly once)
Flink 透過回退和重新傳送 source 資料流從故障中恢復,當理想情況被描述為精確一次時,這並不意味著每個事件都將被精確一次處理。相反,這意味著 每一個事件都會影響 Flink 管理的狀態精確一次。

Barrier 只有在需要提供精確一次的語義保證時需要進行對齊(Barrier alignment)。如果不需要這種語義,可以透過配置 CheckpointingMode.AT_LEAST_ONCE 關閉 Barrier 對齊來提高效能。

端到端精確一次 #
為了實現端到端的精確一次,以便 sources 中的每個事件都僅精確一次對 sinks 生效,必須滿足以下條件:

你的 sources 必須是可重放的,並且
你的 sinks 必須是事務性的(或冪等的)

相關文章