Flink Exactly Once
Flink Exactly Once 語意是基於Chandy-Lamport這個算法的思想的改進版,引入了barrier,可以在不停止整個流處理系統的前提下,保存和恢復每個subtask的snapshot,讓每個節點獨立地做狀態保存和恢復。
Chandy-Lamport 算法
- Initiating a snapshot: 也就是開始創建 snapshot,可以由系統中的任意一個進程發起
- Propagating a snapshot: 系統中其他進程開始逐個創建 snapshot 的過程
- Terminating a snapshot: 算法結束條件
一、Initiating a snapshot
- 進程 Pi 發起: 記錄自己的進程狀態,同時生產一個標識信息 marker,marker 和進程通信的 message 不同
- 將 marker 信息通過 ouput channel 發送給系統裏面的其他進程
- 開始記錄所有 input channel 接收到的 message
二、Propagating a snapshot
- 對於進程 Pj 從 input channel 接收到 marker 信息:
- 如果 Pj 還沒有記錄自己的進程狀態,則
- Pj 記錄自己的進程狀態
- 向 output channel 發送 marker 信息
- 否則
- 記錄所有input channel 中收到所有排在本次mark標識之前的 message。
三、Terminating a snapshot
- 所有的進程都收到 marker 信息並且記錄下自己的狀態和 channel 的狀態(包含的 message)
例子:
C:代表channel,X/Y/Z 代表進程狀態變量,P: 代表進程
初始狀態:
P1發起快照,插入marker
P2接收到Marker開始進行本地快照
P1 接收到 [M1, marker] 信息,記錄M1
所有 的進程都做了快照之後,途中藍色部分就是本次全局快照的內容。
Flink Barrier 機制
數據源設置barrier,觸發task的snapshot
Flink的Job Manager會往所有Source的流中放入一個barrier(圖中三角形),barrier包含當前checkpoint的ID。
當barrier經過一個subtask時,即表示當前這個subtask處於要觸發“快照”,這個節點執行checkpoint方法將當前的state進行持久存儲,然後將這個barrier繼續往下傳遞。下圖中Source1和Source2就是完成了checkpoint動作,然後繼續把id爲2的barrier繼續往下傳遞。
Barrier對齊,對應不同的語意
在分佈式系統中,如果一個subtask有多個上游節點,這個subtask就需要等待所有上游發來的barrier(同一個序號的)都接收到,才能表示這個subtask到達了checkpoint觸發的“時刻”,開始做“快照”,否則這個節點出故障恢復時無法確定該從哪個checkpoint恢復,造成數據不準確,這就是對齊barrier。
At-Most-Once:
當不採用checkpoint時,每個event做多就只會被處理一次,這就是At-Most-Once。
At-Least-once:
當不開啓Barrier對齊時,假設source1的Barrier先到達,那麼後續的source1的數據就接着處理了,比如從數據3開始是本次Barrier之後的數據,這樣等source2的Barrier到達後開始snapshot。如果此時從本次snapshot回覆,那麼source1的數據,從3開始就會有重複。
Exactly-Once:每個subtask都做barrier對齊,這樣就會有一些性能消耗和延遲。
參考: