11張圖,拿下Flink端到端嚴格一次Exactly-Once

11張圖,拿下Flink端到端嚴格一次Exactly-Once——-原文連結

在 Flink 面試中,例如 Flink 如何保證 Exactly-Once 語義?Flink 怎麼保證精準一次消費?Flink 任務如何實現端到端一致?這樣的問題經常會被問到,同時也讓很多求職者頭疼,現在,阿周帶你從頭到尾,

徹底搞懂Flink Exactly-Once語義,從此再也不慫面試官!

我們知道,要想搞懂一個知識點,最好的辦法就是帶著問題去思考,好了,廢話不多說,直接上乾貨!

11張圖,拿下Flink端到端嚴格一次Exactly-Once

Exactly-Once語義 : 指

端到端

的一致性,從

資料讀取

引擎計算

寫入外部儲存的

整個過程中,

即使機器或軟體出現故障,

都確保資料僅處理一次,不會重複、也不會丟失。

11張圖,拿下Flink端到端嚴格一次Exactly-Once

流系統要實現Exactly-Once,需要保證上游 Source 層、中間計算層和下游 Sink 層三部分同時滿足

端到端嚴格一次處理,如下圖:

11張圖,拿下Flink端到端嚴格一次Exactly-Once

Flink端到端嚴格一次處理

Source端:

資料從上游進入Flink,必須保證訊息嚴格一次消費。同時Source 端必須滿足可重放(replay)。否則 Flink 計算層收到訊息後未計算,卻發生 failure 而重啟,訊息就會丟失。

Flink計算層:

利用 Checkpoint 機制,把狀態資料定期持久化儲存下來,Flink程式一旦發生故障的時候,可以選擇狀態點恢復,避免資料的丟失、重複。

Sink端:

Flink將處理完的資料傳送到Sink端時,透過

兩階段提交協議 ,

即 TwoPhaseCommitSinkFunction 函式。該 SinkFunction 提取並封裝了兩階段提交協議中的公共邏輯,保證Flink 傳送Sink端時實現嚴格一次處理語義。

同時:

Sink端必須支援

事務機制

,能夠進行資料

回滾

或者滿足

冪等性。

回滾機制:

即當作業失敗後,能夠將部分寫入的結果回滾到之前寫入的狀態。

冪等性:

就是一個相同的操作,無論重複多少次,造成的結果和只操作一次相等。即當作業失敗後,寫入部分結果,但是當重新寫入全部結果時,不會帶來負面結果,重複寫入不會帶來錯誤結果。

11張圖,拿下Flink端到端嚴格一次Exactly-Once

兩階段提交協議(Two -Phase Commit,2PC)是解決分散式事務問題最常用的方法,它可以保證在分散式事務中,要麼所有參與程序都提交事務,要麼都取消,即實現ACID中的 A(原子性)。

兩階段提交協議中 有兩個重要角色

,協調者(Coordinator)

參與者(Participant)

,其中協調者只有一個,起到分散式事務的協調管理作用,參與者有多個。

兩階段提交階段分為兩個階段:

投票階段(Voting)

提交階段(Commit)。

投票階段:

(1)協調者向所有參與者

傳送 prepare 請求

和事務內容,詢問是否可以準備事務提交,等待參與者的相應。

(2)參與者執行事務中包含的操作,並記錄 undo 日誌(用於回滾)和 redo 日誌(用於重放),但不真正提交。

(3)參與者向協調者返回事務操作的執行結果,執行成功返回yes,失敗返回no。

提交階段:

分為成功與失敗兩種情況。

若所有參與者都返回 yes,說明事務可以提交:

協調者向所有參與者傳送 commit 請求。

參與者收到 commit 請求後,將事務真正地提交上去,並釋放佔用的事務資源,並向協調者返回 ack 。

協調者收到所有參與者的 ack 訊息,事務成功完成,如下圖:

11張圖,拿下Flink端到端嚴格一次Exactly-Once

11張圖,拿下Flink端到端嚴格一次Exactly-Once

若有參與者返回 no 或者超時未返回,說明事務中斷,需要回滾:

協調者向所有參與者傳送rollback請求。

參與者收到rollback請求後,根據undo日誌回滾到事務執行前的狀態,釋放佔用的事務資源,並向協調者返回ack。

協調者收到所有參與者的ack訊息,事務回滾完成。

11張圖,拿下Flink端到端嚴格一次Exactly-Once

11張圖,拿下Flink端到端嚴格一次Exactly-Once

11張圖,拿下Flink端到端嚴格一次Exactly-Once

Flink透過兩階段提交協議來保證Exactly-Once語義。

對於Source端:

Source端嚴格一次處理比較簡單,因為資料要進入Flink 中,所以Flink 只需要儲存消費資料的偏移量 (offset)即可。如果Source端為 kafka,Flink 將 Kafka Consumer 作為 Source,可以將偏移量儲存下來,如果後續任務出現了故障,恢復的時候可以由聯結器重置偏移量,重新消費資料,保證一致性。

對於 Sink 端:

Sink 端是最複雜的,因為資料是落地到其他系統上的,資料一旦離開 Flink 之後,Flink 就監控不到這些資料了,所以嚴格一次處理語義必須也要應用於 Flink 寫入資料的外部系統,

故這些外部系統必須提供一種手段允許提交或回滾這些寫入操作

,同時還要保證與 Flink Checkpoint 能夠協調使用(

Kafka 0.11 版本已經實現精確一次處理語義

)。

我們以

Kafka - Flink -Kafka

為例 說明如何保證Exactly-Once語義。

11張圖,拿下Flink端到端嚴格一次Exactly-Once

如上圖所示:Flink作業包含以下運算元。

(1)一個Source運算元,從Kafka中讀取資料(即KafkaConsumer)

(2)一個視窗運算元,基於時間視窗化的聚合運算(即window+window函式)

(3)一個Sink運算元,將結果寫會到Kafka(即kafkaProducer)

Flink使用兩階段提交協議

預提交(Pre-commit)

階段和

提交(Commit)階段保證端到端嚴格一次。

(1)預提交階段

1、當Checkpoint 啟動時,進入預提交階段

,JobManager 向Source Task 注入檢查點分界線(CheckpointBarrier),Source Task 將 CheckpointBarrier 插入資料流,向下遊廣播開啟本次快照,如下圖所示:

11張圖,拿下Flink端到端嚴格一次Exactly-Once

預處理階段: Checkpoint 啟動

2、Source 端:Flink Data Source 負責儲存 KafkaTopic 的 offset偏移量

,當 Checkpoint 成功時 Flink 負責提交這些寫入,否則就終止取消掉它們,當 Checkpoint 完成位移儲存,它會將 checkpoint barrier(檢查點分界線) 傳給下一個 Operator,然後每個運算元會對當前的狀態做個快照,儲存到

狀態後端(State Backend)

對於 Source 任務而言,就會把當前的 offset 作為狀態儲存起來。下次從 Checkpoint 恢復時,Source 任務可以重新提交偏移量,從上次儲存的位置開始重新消費資料,如下圖所示:

11張圖,拿下Flink端到端嚴格一次Exactly-Once

預處理階段:checkpoint barrier傳遞 及 offset 儲存

3、Slink 端:

從 Source 端開始,每個內部的 transformation 任務遇到 checkpoint barrier(檢查點分界線)時,都會把狀態存到 Checkpoint 裡。資料處理完畢到 Sink 端時,Sink 任務首先把資料寫入外部 Kafka,

這些資料都屬於預提交的事務(還不能被消費)

此時的 Pre-commit 預提交階段下Data Sink 在儲存狀態到狀態後端的同時還必須預提交它的外部事務,

如下圖所示:

11張圖,拿下Flink端到端嚴格一次Exactly-Once

預處理階段:預提交到外部系統

(2)提交階段

4、當所有運算元任務的快照完成

(所有建立的快照都被視為是 Checkpoint 的一部分),

也就是這次的 Checkpoint 完成時

JobManager 會向所有任務發通知,確認這次 Checkpoint 完成,此時 Pre-commit 預提交階段才算完成

。才正式到兩階段提交協議的

第二個階段:commit 階段

。該階段中 JobManager 會為應用中每個 Operator 發起 Checkpoint 已完成的回撥邏輯。

本例中的 Data Source 和視窗操作無外部狀態,因此在該階段,這兩個 Opeartor 無需執行任何邏輯,

但是 Data Sink 是有外部狀態的,此時我們必須提交外部事務

,當 Sink 任務收到確認通知,就會正式提交之前的事務,Kafka 中未確認的資料就改為“已確認”,資料就真正可以被消費了,如下圖所示:

11張圖,拿下Flink端到端嚴格一次Exactly-Once

提交階段:資料精準被消費

注:Flink 由 JobManager 協調各個 TaskManager 進行 Checkpoint 儲存,Checkpoint 儲存在 StateBackend(狀態後端) 中,預設 StateBackend 是記憶體級的,也可以改為檔案級的進行持久化儲存。

11張圖,拿下Flink端到端嚴格一次Exactly-Once

11張圖,拿下Flink端到端嚴格一次Exactly-Once

此圖建議儲存,總結全面且簡明扼要,再也不慫面試官!

以上就是全部講解內容!創造不易啊,畫圖全是自己畫的,不想被白嫖哦,各位「三連」走起就是對博主創作的最大支援和動力了,我們下次見!

為回饋廣大計算機愛好者,本博主專門整理了關於Java、大資料、演算法、前端、人工智慧、作業系統、網路等所學知識的書籍,如果看到此博文的小夥伴們,覺得對你有幫助,請關注微信公眾號:

3分鐘秒懂大資料

,回覆:

福利

。就快速領取吧!

11張圖,拿下Flink端到端嚴格一次Exactly-Once