本文爲翻譯flink作者之一Fabian Hueske的文章
原文:https://www.ververica.com/blog/how-apache-flink-manages-kafka-consumer-offsets
在Flink Friday Tip這集中,我們通過一步步的樣例解釋了Apache Flink是如何協作Apache Kafka保障從Kafka Topics裏處理並保證exactly-once。
Checkpointing是Apache Flink用來故障恢復的內部機制。一次checkpoint是一次Flink應用state的統一拷貝並且包括輸入端的讀取位置。在一次失敗case中,Flink恢復應用通過加載應用checkpoint的state並且從恢復的位置繼續讀取就像什麼都沒有發生一樣。你可以理解checkpoint爲電腦遊戲中的保存當前遊戲進度。如果在你保存遊戲位置後發生了些事情,你可以回退到過去並且重試。
Checkpoints讓Apache Flink有了容錯並且確保了流處理應用在發生失敗時的語義。Checkpoints是可以通過配置定時觸發的。
Flink 中的Kafka Consumer被整合進了Flink的checkpointing機制,像一個存儲了所有Kafka Partitions的offset狀態的狀態算子。當checkpoint觸發,每個partition的offsets被存儲到checkpoint。FLink的checkpoint機制確保存儲的全部算子的任務是統一的,即它們基於同樣的輸入源數據。一次checkpoint當所有的算子任務成功存儲狀態後記作是完成。於是,系統在從潛在的系統失敗重啓時,提供了exactly-once狀態保障。
下面我們通過一步步的指示描述了Apache Flink 如何處理checkpoints 在Kafka consumer offsets場景。在我們的例子裏,數據存儲在FLink job Master。要注意的是這裏是在POC或生產用例,數據通常存儲在外部文件系統比如HDFS或者S3。
Step1
下面例子從Kafka topic 兩個partitions讀取數據,每個partition包含A,B,C,D,E消息。我們設置每個partitions的offset爲0。
Step2
第二步,kafka consumer開始讀取partition 0消息。消息A在飛行(in-flight)被處理並且第一個consumer offset改爲1.
Step3
第三步,消息A到達Map任務。每個consumer讀取各自的下個記錄(在partition0中是消息B,在partition1中是消息A)。offsets分別被更新爲2和1在兩個partition。在同時,Flink的Job Master判定觸發一次checkpoint在源。
Step4
接下來階段,kafka consumer的任務已經創建了一個屬於它們狀態的快照(offset=2,1)在Job Master中。源頭髮送一次checkpoint barrier(不懂可以google下)用來對齊所有算子任務和保證總體checkpoint的一致性。消息A到達map任務時頭部consmer繼續讀取下條消息(消息C)
Step5
這個階段展示了flink map任務從兩個源接收barrier,並且checkpoint它的狀態到Job Master。與此同時,consumer繼續從kafka partition讀取更多事件。
Step6
這個階段展示Map任務一旦checkpoint state完成後與Job Master的交互。當job的所有任務checkpoint完成和響應時,Job Master完成checkpoint。從現在開始,checkpoint可以用來故障恢復。值得一提的是Apache FLink 不依賴kafka的offsets機制來恢復潛在的系統錯誤
Recovery in case of a failure
在失敗例子中(例如,一個worker失敗)所有的算子任務被重啓並且它們的狀態被重置到最後一次checkpoint。像下圖描述的一樣。
Kafka源開始消費分別在2和1的位點,在已完成checkpoint的offset。當job重啓時我們期望一個普通系統就像沒有錯誤發生一樣。