kafka兩階段提交、冪等以及flink結合

1 在checkpoint之間是一直pre_commit, 數據寫入kafka broker, 同時在transaction協調器以及 消費者處理器之間寫入本次事務的元信息;等到本次從source到sink之間的checkpoint全部完成,job manager完成checkpoint時,sink的producer才正式發出事務commit,這時候kafka之前寫入broker的log纔會對消費者顯示有效可以讀取。

以下信息取自:https://zhuanlan.zhihu.com/p/111304281

具體代碼層面:

flink kafkasink的TwoPhaseCommitSinkFunction仍然留了以下四個抽象方法待子類來實現:

beginTransaction():開始一個事務,返回事務信息的句柄。

preCommit():預提交(即提交請求)階段的邏輯。

commit():正式提交階段的邏輯。

abort():取消事務

這四個方法實際上是flink對於sink端支持兩階段事務提交中間件的抽象,具體針對kafka sink來說,應用了kafka對應的兩階段提交的方法。

1.1 預提交階段

FlinkKafkaProducer011.preCommit()方法的實現很簡單。其中的flush()方法實際上是代理了KafkaProducer.flush()方法。

那麼preCommit()方法是在哪裏使用的呢?答案是TwoPhaseCommitSinkFunction.snapshotState()方法。從前面的類圖可以得知,TwoPhaseCommitSinkFunction也繼承了CheckpointedFunction接口,所以2PC是與檢查點機制一同發揮作用的。

每當需要做checkpoint時,JobManager就在數據流中打入一個屏障(barrier),作爲檢查點的界限。屏障隨着算子鏈向下遊傳遞,每到達一個算子都會觸發將狀態快照寫入狀態後端(state BackEnd)的動作。當屏障到達Kafka sink後,觸發preCommit(實際上是KafkaProducer.flush())方法刷寫消息數據,但還未真正提交。接下來還是需要通過檢查點來觸發提交階段。

1.2 提交階段

FlinkKafkaProducer011.commit()方法實際上是代理了KafkaProducer.commitTransaction()方法,正式向Kafka提交事務。

該方法的調用點位於TwoPhaseCommitSinkFunction.notifyCheckpointComplete()方法中。顧名思義,當所有檢查點都成功完成之後,會回調這個方法。

該方法每次從正在等待提交的事務句柄中取出一個,校驗它的檢查點ID,並調用commit()方法提交之。

1.3 回退階段

可見,只有在所有檢查點都成功完成這個前提下,寫入纔會成功。這符合前文所述2PC的流程,其中JobManager爲協調者,各個算子爲參與者(不過只有sink一個參與者會執行提交)。一旦有檢查點失敗,notifyCheckpointComplete()方法就不會執行。如果重試也不成功的話,最終會調用abort()方法回滾事務。

 

2 kafka的冪等性可以防止重複提交。每個producer可以用戶顯式的指定transactionId, 這樣producer Id以及topic、partition和生產者發送的每條消息的遞增的seq Id.這些可以唯一確定一條消息,相當於唯一鍵,防止broker內部數據重複寫入。

 

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