Flink Internals - Data Streaming Fault Tolerance(數據流容錯)

簡介

Apache Flink 提供了一種容錯機制來一致地恢復數據流應用程序的狀態。該機制確保即使存在故障,程序的狀態最終將精確地反映數據流中的每條記錄一次。注意,這裏有一個開關,將擔保降級到至少一次(如下所述)。

容錯機制連續繪製分佈式流數據流的快照。對於狀態小的流應用程序,這些快照非常輕量級,可以頻繁地繪製,不會對性能造成很大影響。流應用程序的狀態存儲在一個可配置的位置(如主節點或HDFS)。

如果程序失敗(由於機器、網絡或軟件故障),Flink將停止分佈式流數據流。然後系統重新啓動算子,並將它們重新設置爲最新的成功檢查點。輸入流被重置到狀態快照的點。作爲重新啓動的並行數據流的一部分處理的任何記錄都保證不屬於以前的檢查點狀態的一部分。

注意:默認情況下,檢查點是禁用的。

爲了實現這種機制的完全保證,數據流源(如消息隊列或代理)需要能夠將流回退到定義的最近點。Apache Kafka 有這個能力,Flink 的 Kafka 連接器利用了這個能力。

因爲 Flink 的檢查點是通過分佈式快照實現的,所以我們可以交替使用快照和檢查點這兩個詞。

Checkpointing

Flink 容錯機制的核心部分是繪製分佈式數據流和操作符狀態的一致快照。這些快照充當一致的檢查點,在出現故障時,系統可以退回到這些檢查點。Flink繪製這些快照的機制在“分佈式數據流的輕量級異步快照”中進行了描述。它的靈感來自於分佈式快照的標準Chandy-Lamport算法,並特別針對Flink的執行模型進行了調整。

Barriers

Flink 分佈式快照的核心元素是流 barriers。這些 barriers 被注入到數據流中,並與記錄一起作爲數據流的一部分。barriers 永遠不會超過記錄,它們嚴格地按順序流動。barriers 將數據流中的記錄分隔爲進入當前快照的記錄集和進入下一個快照的記錄集。每個 barriers 攜帶快照的ID,快照將快照的記錄推到它前面。barriers 不會打斷數據流,因此非常輕量級。來自不同快照的多個 barriers 可能同時出現在流中,這意味着各種快照可能同時發生。

流 barrier 被注入流源處的並行數據流。快照n的 barrier 被注入的位置(我們稱之爲Sn)是源流中快照覆蓋數據的位置。例如,在 Apache Kafka 中,這個位置是分區中最後一條記錄的偏移量。這個位置的Sn被報告給檢查點協調器(Flink的JobManager)。

這些 barrier 隨後會順流而下。當中間算子從它的所有輸入流接收到快照n的 barriers 時,它將快照n的 barrier 發送到它的所有傳出流。一旦接收算子(流DAG的末端)從其所有輸入流接收到 barrier n,它就向檢查點協調器確認快照n。在所有接收確認了快照之後,就認爲完成了快照。

快照n完成後,作業將不再向源請求來自Sn之前的記錄,因爲此時這些記錄(及其後代記錄)將通過整個數據流拓撲。

接收多個輸入流的算子需要對齊快照 barrier 上的輸入流。上圖說明了這一點:

  • 一旦算子從傳入流接收到快照 barrier n,它就不能處理來自該流的任何其他記錄,直到它也從其他輸入接收到 barrier n。否則,它將混合屬於 snapshot n 的記錄和屬於 snapshot n+1的記錄。
  • 報告 barrier n 的流被暫時擱置。從這些流接收的記錄不會被處理,而是被放入輸入緩衝區。
  • 一旦最後一個流接收到 barrier n,算子將發出所有掛起的傳出記錄,然後發出 snapshot n barrier 本身。
  • 之後,它繼續處理來自所有輸入流的記錄,在處理來自流的記錄之前處理來自輸入緩衝區的記錄。

State

當算子包含任何形式的狀態時,該狀態也必須是快照的一部分。算子狀態有不同的形式:

  • User-defined state:這是由轉換函數(如map()或filter())直接創建和修改的狀態。
  • System state:這種狀態指的是屬於運算符計算的一部分的數據緩衝區。這種狀態的典型例子是窗口緩衝區,系統在其中收集(和聚合)窗口的記錄,直到計算和清除窗口爲止。

算子在從其輸入流接收到所有快照 barrier 並在將 barrier 發送到其輸出流之前對其狀態進行快照。此時,barrier 之前的記錄對狀態的所有更新都已完成,而 barrier 應用之後,依賴於記錄的更新將不再發生。因爲快照的狀態可能很大,所以它存儲在可配置的狀態後端。默認情況下,這是 JobManager 的內存,但是對於生產使用,應該配置分佈式可靠存儲(例如HDFS)。在存儲狀態之後,算子確認檢查點,將快照屏障發送到輸出流中,然後繼續。

結果快照現在包含:

  • 對於每個並行流數據源,在快照啓動時流中的偏移/位置
  • 對於每個算子,都有一個指向存儲爲快照一部分的狀態的指針

高清圖片地址:https://ci.apache.org/projects/flink/flink-docs-release-1.9/fig/checkpointing.svg

Exactly Once vs. At Least Once

對齊步驟可能會增加流程序的延遲。通常,這種額外的延遲大約是幾毫秒,但是我們已經看到一些異常值的延遲明顯增加的情況。對於所有記錄都需要一致的超低延遲(幾毫秒)的應用程序,Flink有一個開關來跳過檢查點期間的流對齊。當算子看到來自每個輸入的檢查點屏障時,檢查點快照仍然被繪製。

當跳過隊列時,操作人員將繼續處理所有輸入,即使在檢查點n的某些檢查點屏障到達之後也是如此。這樣,操作人員還可以在獲取檢查點n的狀態快照之前處理屬於檢查點n+1的元素。在恢復時,這些記錄將以重複的形式出現,因爲它們都包含在檢查點n的狀態快照中,並將在檢查點n之後作爲數據的一部分重新發送。

具有多個前算子(join)和多個發送者(在流重新分區/ shuffle 之後)的算子纔會發生對齊。因此,只有並行流操作(map()、flatMap()、filter()、…)的數據流實際上只提供一次保證,即使在至少一次模式下也是如此。

異步狀態快照

注意,上面描述的機制意味着算子在將狀態快照存儲在狀態後端時停止處理輸入記錄。此同步狀態快照在每次捕獲快照時都會引入延遲。

可以讓算子在存儲狀態快照時繼續處理,從而有效地讓狀態快照在後臺異步發生。爲此,算子必須能夠生成一個狀態對象,該對象應該以一種對操作符狀態的進一步修改不會影響該狀態對象的方式存儲。例如,在 RocksDB 中使用的即寫即拷數據結構具有這種行爲。

在接收到其輸入上的檢查點 barrier 之後,算子開始對其狀態進行異步快照複製。它立即向其輸出發出屏障,並繼續常規的流處理。一旦後臺複製過程完成,它向檢查點協調器(JobManager)確認檢查點。檢查點現在只有在所有的接收點接收到 barrier 並且所有有狀態算子都已確認它們的完整備份(可能是在 barrier 到達接收點之後)之後才完成。

3.6、Flink流處理(Stream API)- State & Fault Tolerance(狀態和容錯)之 State Backends(狀態後端)

恢復

這種機制下的恢復非常簡單:在發生故障時,Flink 選擇最新完成的檢查點k,然後系統重新部署整個分佈式數據流,並向每個算子提供作爲檢查點k一部分快照的狀態。源被設置爲從位置Sk開始讀取流。例如在 Apache Kafka 中,這意味着告訴消費者從偏移Sk開始獲取。

如果以增量方式快照狀態,則操作符從最新的完整快照狀態開始,然後對該狀態應用一系列增量快照更新。

Flink Managing Execution - Task Failure Recovery(Flink Task 故障恢復)

算子快照實現

在獲取算子快照時,有兩個部分:synchronous asynchronous

算子和狀態後端將它們的快照作爲 Java FutureTask 提供。該任務包含同步部分完成和異步部分掛起的狀態。異步部分然後由該檢查點的後臺線程執行。

檢查點操作符完全同步地返回一個已經完成的 FutureTask。如果需要執行異步操作,則在 FutureTask 的run()方法中執行。

這些任務是可取消的,因此可以釋放流和其他資源消耗句柄。

 

原文地址:https://ci.apache.org/projects/flink/flink-docs-release-1.9/internals/stream_checkpointing.html

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