Flink-狀態一致性 | 狀態一致性分類 | 端到端狀態一致性 | 冪等寫入 | 事務寫入 | WAL | 2PC

狀態一致性

當在分佈式系統中引入狀態時,自然也引入了一致性問題。一致性實際上是"正確性級別"的另一種說法,也就是說在成功處理故障並恢復之後得到的結果,與沒有發生任何故障時得到的結果相比,前者到底有多正確?舉例來說,假設要對最近一小時登錄的用戶計數。在系統經歷故障之後,計數結果是多少?如果有偏差,是有漏掉的計數還是重複計數?

什麼是狀態一致性

  1. 有狀態的流處理,內部每個算子任務都可以有自己的狀態
  2. 對於流處理器內部來說,所謂的狀態一致性,其實就是我們所說的計算結果要保證準確。
  3. 一條數據不應該丟失,也不應該重複計算
  4. 在遇到故障時可以恢復狀態,恢復以後的重新計算,結果應該也是完全正確的。

在這裏插入圖片描述

狀態一致性分類

Flink的一個重大價值在於,它既保證了exactly-once,也具有低延遲和高吞吐的處理能力。

  1. AT-MOST-ONCE(最多一次)
    當任務故障時,最簡單的做法是什麼都不幹,既不恢復丟失的狀態,也不重播丟失的數據。At-most-once 語義的含義是最多處理一次事件。這其實是沒有正確性保障的委婉說法——故障發生之後,計數結果可能丟失。同樣的還有udp。
  2. AT-LEAST-ONCE(至少一次)
    在大多數的真實應用場景,我們希望不丟失事件。這種類型的保障稱爲 at-least-once,意思是所有的事件都得到了處理,而一些事件還可能被處理多次。這表示計數結果可能大於正確值,但絕不會小於正確值。也就是說,計數程序在發生故障後可能多算,但是絕不會少算。
  3. EXACTLY-ONCE(精確一次)
    恰好處理一次是最嚴格的保證,也是最難實現的。恰好處理一次語義不僅僅意味着沒有事件丟失,還意味着針對每一個數據,內部狀態僅僅更新一次。這指的是系統保證在發生故障後得到的計數結果與正確值一致。

一致性檢查點(Checkpoints)

在這裏插入圖片描述
在這裏插入圖片描述

端到端(end-to-end)狀態一致性

  1. 內部保證 —— 依賴checkpoint
  2. source 端 —— 需要外部源可重設數據的讀取位置
  3. sink 端 —— 需要保證從故障恢復時,數據不會重複寫入外部系統
    冪等寫入
    事務寫入

在這裏插入圖片描述

冪等寫入(Idempotent Writes)

所謂冪等操作,是說一個操作,可以重複執行很多次,但只導致一次結果更改,也就是說,後面再重複執行就不起作用了。
在這裏插入圖片描述

事務寫入(Transactional Writes)

需要構建事務來寫入外部系統,構建的事務對應着 checkpoint,等到 checkpoint 真正完成的時候,才把所有對應的結果寫入 sink 系統中。

在這裏插入圖片描述

預寫日誌(Write-Ahead-Log,WAL)

在這裏插入圖片描述

兩階段提交(Two-Phase-Commit,2PC)

真正得用一個事務來保證
在這裏插入圖片描述

不同 Source 和 Sink 的一致性

在這裏插入圖片描述

Flink+Kafka 端到端狀態一致性的保證

在這裏插入圖片描述

Exactly-once 兩階段提交

  1. JobManager 協調各個 TaskManager 進行 checkpoint 存儲
  2. checkpoint保存在 StateBackend中,默認StateBackend是內存級的,也可以改爲文件級的進行持久化保存

在這裏插入圖片描述

  1. 當 checkpoint 啓動時,JobManager 會將檢查點分界線(barrier)注入數據流
  2. barrier會在算子間傳遞下去

在這裏插入圖片描述

  1. 每個算子會對當前的狀態做個快照,保存到狀態後端
  2. checkpoint 機制可以保證內部的狀態一致性

在這裏插入圖片描述

  1. 每個內部的 transform 任務遇到 barrier 時,都會把狀態存到 checkpoint 裏
  2. sink 任務首先把數據寫入外部 kafka,這些數據都屬於預提交的事務;遇到 barrier 時,把狀態保存到狀態後端,並開啓新的預提交事務

在這裏插入圖片描述

  1. 當所有算子任務的快照完成,也就是這次的 checkpoint 完成時,JobManager 會向所有任務發通知,確認這次 checkpoint 完成
  2. sink 任務收到確認通知,正式提交之前的事務,kafka 中未確認數據改爲“已確認”

在這裏插入圖片描述

Exactly-once 兩階段提交步驟總結

  1. 第一條數據來了之後,開啓一個 kafka 的事務(transaction),正常寫入 kafka 分區日誌但標記爲未提交,這就是“預提交”
  2. jobmanager 觸發 checkpoint 操作,barrier 從 source 開始向下傳遞,遇到 barrier 的算子將狀態存入狀態後端,並通知 jobmanager
  3. sink 連接器收到 barrier,保存當前狀態,存入 checkpoint,通知 jobmanager,並開啓下一階段的事務,用於提交下個檢查點的數據
  4. jobmanager 收到所有任務的通知,發出確認信息,表示 checkpoint 完成
  5. sink 任務收到 jobmanager 的確認信息,正式提交這段時間的數據
  6. 外部kafka關閉事務,提交的數據可以正常消費了。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章