Flink流式框架的狀態一致性

一、狀態一致性

1)有狀態的流處理,內部每個算子任務都可以有自己的狀態;

2)對於流處理器內部來說,所謂的狀態一致性,其實就是我們所說的計算結果要保證準確;

3)一條數據不應該丟失,也不應該重複計算;

4)在遇到故障時可以恢復狀態,恢復以後進行重新計算,結果應該也是完全正確的;

 

1、狀態一致性分類

(1)AT-MOST-ONCE(最多一次)

  》》當任務故障時,最簡單的做法就是什麼也不幹,既不恢復丟失的狀態,也不重播丟失的數據,At-most-once語義的含義是最多處理一次事件。

(2)AT-LEAST-ONCE(至少一次)

   》》在大多數的真實應用場景中,我們希望不丟失事件,這種類型的保障稱爲at-least-once,意思是所有的事件都得到了處理,而一些事件還可能被處理多次;

(3)EXACTLY-ONCE(精確一次)

   》》恰好處理一次是最嚴格的保證,也是最難實現的。恰好處理一次語義不僅僅意味着沒有事件丟失,還意味着針對每一個數據,內部狀態僅僅更新一次。

 

二、一致性檢查點(checkpoint)

1)Flink使用了一種輕量級快照機制——檢查點(checkpoint)來保證exactly-once語義;

2)有狀態流應用的一致檢查點,其實就是:所有任務的狀態,在某個時間點的一份拷貝(一份快照)。而這個時間點,應該是所有任務都恰好處理完一個相同的輸入數據的時候;

3)應用狀態的一致檢查點,是Flink故障恢復機制的核心;

 

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

1)目前我們看到的一致性保證都是由流處理器實現的,也就是說都是在Flink流處理器內部保證的;而在真實應用中,流處理應用除了流處理器以外還包含了數據源(例如:Kafka)和輸出到持久化系統;

2)端到端的一致性保證,意味着結果的正確性貫穿了整個流處理應用的始終;每一個組件都保證了它自己的一致性;

3)整個端到端的一致性級別取決於所有組件中一致性最弱的組件;

 

四、端到端的精確一次(exactly-once)保證

1)內部保證——checkpoint;

2)source端——可重設數據的讀取位置

3)sink端——從故障恢復時,數據不會重複寫入外部系統

      》》冪等寫入

      》》事務寫入

 

1、冪等寫入(Idempotent  Writes)

1)所謂冪等操作,是說一個操作,可以重複執行很多次,但只導致一次結果更改,也就是說,後面再重複執行就不起作用了;

 

2、事務寫入(Transactional  Writes)

1)事務(Transaction)

      》》應用程序中一系列嚴密的操作,所有操作必須成功完成,否則在每個操作中所做的所有更改都會被撤銷;

      》》具有原子性:一個事務中的一系列操作要麼全部成功,要麼一個都不做;

2)實現思想:構建的事務對應着checkpoint,等到checkpoint真正完成的時候,才把所有對應的結果寫入sink系統中;

3)實現方式:預寫日誌、兩階段提交;

 

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

1)把結果數據先當成狀態保存,然後在收到checkpoint完成的通知時,一次性寫入sink系統;

2)簡單易於實現,由於數據提前在狀態後端中做了緩存,所以無論什麼sink系統,都能用這種方式一批搞定;

3)DataStream  API提供了一個模版類:GenericWriteAheadSink,來實現這種事務性sink;

 

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

1)對於每個checkpoint,sink任務會啓動一個事務,並將接下來所有接收的數據添加到事務裏;

2)然後將這些數據寫入外部sink系統,但不提交它們——這時只是“預提交”;

3)當它收到checkpoint完成的通知時,它才正式提交事務,實現結果的真正寫入;

4)這種方式真正實現了exactly-once,它需要一個提供事務支持的外部sink系統。Flink提供了TwoPhaseCommitSinkFunction接口;

 

2.3  2PC對外部sink系統的要求

1)外部sink系統必須提供事務支持,或者sink任務必須能夠模擬外部系統上的事務;

2)在checkpoint的間隔期間裏,必須能夠開啓一個事務並接收數據寫入;

3)在收到checkpoint完成的通知之前,事務必須是“等待提交”的狀態。在故障恢復的情況下,這可能需要一些時間。如果這個時候sink系統關閉事務(例如:超時了),那麼未提交的數據就會丟失;

4)sink任務必須能夠在進程失敗後恢復事務;

5)提交事務必須是冪等操作;

 

2.4  不同Source和Sink的一致性保證

source

sink

不可重置

可重置

任意(Any

At-most-once

At-least-once

冪等

At-most-once

Exactly-once

(故障恢復時會出現暫時不一致)

預寫日誌(WAL

At-most-once

At-least-once

兩階段提交(2PC

At-most-once

Exactly-once

 

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

1)內部——利用checkpoint機制,把狀態存盤,發生故障的時候可以恢復,保證內部的狀態一致性;

2)source——kafka  consumer作爲source,可以將偏移量保存下來,如果後續任務出現了故障,恢復的時候可以由連接器重置偏移量,重新消費數據,保證一致性;

3)sink——kafka  producer作爲sink,採用兩階段提交sink,需要實現一個TwoPhaseCommitSinkFunction;

 

1、Exactly-once兩階段提交

1)JobManager協調各個TaskManager進行checkpoint存儲;

2)checkpoint保存在StateBackend中,默認StateBackend是內存級的,也可以改爲文件級的進行持久化保存;

3)當checkpoint啓動時,JobManager會將檢查點分界線(barrier)注入數據流;

4)barrier會在算子間傳遞下去;

5)每個算子會對當前的狀態做個快照,保存到狀態後端;

6)checkpoint機制可以保證內部的狀態一致性;

7)每個內部的transform任務遇到barrier時,都會把狀態保存到checkpoint裏面;

8)sink任務首先把數據寫入外部kafka,這些數據都屬於預提交的事務;遇到barrier時,把狀態保存到狀態後端,並開啓新的預提交事務;

9)當所有算子任務的快照完成,也就是這次的checkpoint完成時,JobManager會向所有任務發通知,確認這次checkpoint完成;

10)sink任務收到確認通知,正式提交之前的事務,kafka中未確認數據改爲“已確認”;

 

2、 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關閉事務,提交的數據可以正常消費了;

 

 

 

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