文章目錄:
- Apache Flink 應用程序中的 Exactly-Once 語義
- Flink 應用程序端到端的 Exactly-Once 語義
- 示例 Flink 應用程序啟動預提交階段
- 在 Flink 中實現兩階段提交 Operator
- 總結
Apache Flink 自2017年12月發布的1.4.0版本開始,為流計算引入了一個重要的里程碑特性:TwoPhaseCommitSinkFunction(相關的Jira)。它提取了兩階段提交協議的通用邏輯,使得通過Flink來構建端到端的Exactly-Once程序成為可能。同時支持一些數據源(source)和輸出端(sink),包括Apache Kafka 0.11及更高版本。它提供了一個抽象層,用戶只需要實現少數方法就能實現端到端的Exactly-Once語義。
有關TwoPhaseCommitSinkFunction的使用詳見文檔: TwoPhaseCommitSinkFunction。或者可以直接閱讀Kafka 0.11 sink的文檔: kafka。
接下來會詳細分析這個新功能以及Flink的實現邏輯,分為如下幾點。
- 描述Flink checkpoint機制是如何保證Flink程序結果的Exactly-Once的
- 顯示Flink如何通過兩階段提交協議與數據源和數據輸出端交互,以提供端到端的Exactly-Once保證
- 通過一個簡單的示例,瞭解如何使用TwoPhaseCommitSinkFunction實現Exactly-Once的文件輸出
一、Apache Flink應用程序中的Exactly-Once語義
當我們說『Exactly-Once』時,指的是每個輸入的事件隻影響最終結果一次。即使機器或軟體出現故障,既沒有重複數據,也不會丟數據。
Flink很久之前就提供了Exactly-Once語義。在過去幾年中,我們對Flink的checkpoint機制有過深入的描述,這是Flink有能力提供Exactly-Once語義的核心。Flink文檔還提供了該功能的全面概述。
在繼續之前,先看下對checkpoint機制的簡要介紹,這對理解後面的主題至關重要。
- 次checkpoint是以下內容的一致性快照:
- 應用程序的當前狀態
- 輸入流的位置
Flink可以配置一個固定的時間點,定期產生checkpoint,將checkpoint的數據寫入持久存儲系統,例如S3或HDFS。將checkpoint數據寫入持久存儲是非同步發生的,這意味著Flink應用程序在checkpoint過程中可以繼續處理數據。
如果發生機器或軟體故障,重新啟動後,Flink應用程序將從最新的checkpoint點恢復處理; Flink會恢復應用程序狀態,將輸入流回滾到上次checkpoint保存的位置,然後重新開始運行。這意味著Flink可以像從未發生過故障一樣計算結果。
在Flink 1.4.0之前,Exactly-Once語義僅限於Flink應用程序內部,並沒有擴展到Flink數據處理完後發送的大多數外部系統。Flink應用程序與各種數據輸出端進行交互,開發人員需要有能力自己維護組件的上下文來保證Exactly-Once語義。
為了提供端到端的Exactly-Once語義 – 也就是說,除了Flink應用程序內部,Flink寫入的外部系統也需要能滿足Exactly-Once語義 – 這些外部系統必須提供提交或回滾的方法,然後通過Flink的checkpoint機制來協調。
分散式系統中,協調提交和回滾的常用方法是兩階段提交協議。在下一節中,我們將討論Flink的TwoPhaseCommitSinkFunction是如何利用兩階段提交協議來提供端到端的Exactly-Once語義。
二、Flink應用程序端到端的Exactly-Once語義
我們將介紹兩階段提交協議,以及它如何在一個讀寫Kafka的Flink程序中實現端到端的Exactly-Once語義。Kafka是一個流行的消息中間件,經常與Flink一起使用。Kafka在最近的0.11版本中添加了對事務的支持。這意味著現在通過Flink讀寫Kafaka,並提供端到端的Exactly-Once語義有了必要的支持。
Flink對端到端的Exactly-Once語義的支持不僅侷限於Kafka,您可以將它與任何一個提供了必要的協調機制的源/輸出端一起使用。例如Pravega,來自DELL/EMC的開源流媒體存儲系統,通過Flink的TwoPhaseCommitSinkFunction也能支持端到端的Exactly-Once語義。