91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Flink Exactly-Once 投遞的實現淺析是怎樣的

發布時間:2021-11-15 16:07:12 來源:億速云 閱讀:157 作者:柒染 欄目:大數據

這期內容當中小編將會給大家帶來有關Flink Exactly-Once 投遞的實現淺析是怎樣的,文章內容豐富且以專業的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。

本文作者:Paul Lin
文章來源:https://www.whitewood.me

隨著近來越來越多的業務遷移到 Flink 上,對 Flink 作業的準確性要求也隨之進一步提高,其中最為關鍵的是如何在不同業務場景下保證 exactly-once 的投遞語義。雖然不少實時系統(e.g. 實時計算/消息隊列)都宣稱支持 exactly-once,exactly-once 投遞似乎是一個已被解決的問題,但是其實它們更多是針對內部模塊之間的信息投遞,比如 Kafka 生產(producer 到 Kafka broker)和消費(broker 到 consumer)的 exactly-once。而 Flink 作為實時計算引擎,在實際場景業務會涉及到很多不同組件,由于組件特性和定位的不同,Flink 并不是對所有組件都支持 exactly-once(見[1]),而且不同組件實現 exactly-once 的方法也有所差異,有些實現或許會帶來副作用或者用法上的局限性,因此深入了解 Flink exactly-once 的實現機制對于設計穩定可靠的架構有十分重要的意義。
下文將基于 Flink 詳細分析 exactly-once 的難點所在以及實現方案,而這些結論也可以推廣到其他實時系統,特別是流式計算系統。

Exactly-Once 難點分析

由于在分布式系統的進程間協調需要通過網絡,而網絡情況在很多情況下是不可預知的,通常發送消息要考慮三種情況:  正常返回、錯誤返回和超時,其中錯誤返回又可以分為可重試錯誤返回(e.g. 數據庫維護暫時不可用)和不可重試錯誤返回(e.g. 認證錯誤),而可重試錯誤返回和超時都會導致重發消息,導致下游可能接收到重復的消息,也就是 at-least-once 的投遞語義。  而 exactly-once 是在 at-least-once 的基礎之上加上了可以識別出重發數據或者將消息包裝為為冪等操作的機制。
其實消息的 exactly-once 投遞并不是一個分布式系統產生的新課題(雖然它一般特指分布式領域的 exactly-once),早在計算網絡發展初期的 TCP 協議已經實現了網絡的可靠傳輸。  TCP 協議的 exactly-once 實現方式是將消息傳遞變為有狀態的:  首先同步建立連接,然后發送的每個數據包加上遞增的序列號(sequence number),發送完畢后再同步釋放連接。  由于發送端和接受端都保存了狀態信息(已發送數據包的序列號/已接收數據包的序列號),它們可以知道哪些數據包是缺失或重復的。
而在分布式環境下 exactly-once 則更為復雜,最大的不同點在于分布式系統需要容忍進程崩潰和節點丟失,這會帶來許多問題,比如下面常見的幾個:
  • 進程狀態需要持續化到可靠的分布式存儲,以防止節點丟失帶來狀態的丟失。

  • 由于發送消息是一個兩階段的操作(即發送消息和收到對方的確認),重啟之后的進程沒有辦法判斷崩潰前是否已經使用當前序列號發送過消息,因此可能會導致重復使用序列號的問題。

  • 被認為崩潰的進程有可能并沒有退出,隨后再次連上來變為 zombie 進程繼續發送數據。

第2點和第3點其實是同一個問題,即需要區分出原本進程和重啟后的進程。  對此業界已經有比較成熟的解決方案: 引入 epoch 表示進程的不同世代并用分布式協調系統來負責管理。  雖然還有一些衍生的細節問題,但總體來說問題都不大。  但是第1點問題造成了一個比較深遠的影響,即為了減低 IO 成本,狀態的保存必然是微批量(micro-batching)的而不是流式的,這會導致狀態的保存總是落后于流計算進度,因而為了保證 exactly-once 流計算引擎需要實現事務回滾。

狀態 Exactly-Once 和端到端 Exactly-Once

Flink 提供 exactly-once 的狀態(state)投遞語義,這為有狀態的(stateful)計算提供了準確性保證。  其中比較容易令人混淆的一點是狀態投遞語義和更加常見的端到端(end to end)投遞語義,而實現前者是實現后者的前置條件。
Flink 從 0.9 版本開始提供 State API,標志著 Flink 進入了 Stateful Streaming 的時代。  State API 簡單來說是“不受進程重啟影響的“數據結構,其命名規范也與常見的數據結構一致,比如 MapState、ListState。  Flink 官方提供的算子(比如 KafkaSource)和用戶開發的算子都可以使用 State API 來保存狀態信息。  和大多數分布式系統一樣 Flink 采用快照的方式來將整個作業的狀態定期同步到外部存儲,也就是將 State API 保存的信息以序列化的形式存儲,作業恢復的時候只要讀取外部存儲即可將作業恢復到先前某個時間點的狀態。  由于從快照恢復同時會回滾數據流的處理進度,所以 State 是天然的 exactly-once 投遞。
而端到端的一致性則需要上下游的外部系統配合,因為 Flink 無法將它們的狀態也保存到快照并獨立地回滾它們,否則就不叫作外部系統了。  通常來說 Flink 的上游是可以重復讀取或者消費的 pull-based 持續化存儲,所以要實現 source 端的 exactly-once 只需要回滾 source 的讀取進度即可(e.g. Kafka 的 offset)。  而 sink 端的 exactly-once 則比較復雜,因為 sink 是 push-based 的。  所謂覆水難收,要撤回發出去的消息是并不是容易的事情,因為這要求下游根據消息作出的一系列反應都是可撤回的。  這就需要用 State API 來保存已發出消息的元數據,記錄哪些數據是重啟后需要回滾的。
下面將分析 Flink 是如何實現 exactly-once Sink 的。

Exactly-Once Sink 原理

Flink 的 exactly-once sink 均基于快照機制,按照實現原理可以分為冪等(Idempotent) sink 和事務性(Transactional) sink 兩種。

冪等 Sink

冪等性是分布式領域里十分有用的特性,它意味著相同的操作執行一次和執行多次可以獲得相同的結果,因此 at-least-once 自然等同于 exactly-once。  如此一來,在從快照恢復的時候冪等 sink 便不需要對外部系統撤回已發消息,相當于回避了外部系統的狀態回滾問題。  比如寫入 KV 數據庫的 sink,由于插入一行的操作是冪等的,因此 sink 可以無狀態的,在錯誤恢復時也不需要關心外部系統的狀態。  從某種意義來講,上文提到的 TCP 協議也是利用了發送數據包冪等性來保證 exactly-once。
然而冪等 sink 的適用場景依賴于業務邏輯,如果下游業務本來就無法保證冪等性,這時就需要應用事務性 sink。

事務性 Sink

事務性 sink 顧名思義類似于傳統 DBMS 的事務,將一系列(一般是一個 checkpoint 內)的所有輸出包裝為一個邏輯單元,理想的情況下提供 ACID 的事務保證。  之所以說是“理想的情況下”,主要是因為 sink 依賴于目標輸出系統的事務保證,而分布式系統對于事務的支持并不一定很完整,比如 HBase 就不支持跨行事務,再比如 HDFS 等文件系統是不提供事務的,這種情況下 sink 只可以在客戶端的基礎上再包裝一層來盡最大努力地提供事務保證。
然而僅有下游系統本身提供的事務保證對于 exactly-once sink 來說是不夠的,因為同一個 sink 的子任務(subtask)會有多個,對于下游系統來說它們是處在不同會話和事務中的,并不能保證操作的原子性,因此 exactly-once sink 還需要實現分布式事務來達到所有 subtask 的一致 commit 或 rollback。  由于 sink 事務生命周期是與 checkpoint 一一對應的,或者說 checkpoint 本來就是實現作業狀態持久化的分布式事務,sink 的分布式事務也理所當然可以通過 checkpoint 機制提供的 hook 來實現。
Checkpoint 提供給算子的 hook 有 CheckpointedFunction 和 CheckpointListener 兩個,前者在算子進行 checkpoint 快照時被調用,后者在 checkpoint 成功后調用。  為了簡單起見 Flink 結合上述兩個接口抽象出 exactly-once sink 的通用邏輯抽象   TwoPhaseCommitSinkFunction   接口,從命名即可看出這是對兩階段提交協議的一個實現,其主要方法如下:
  • beginTransaction: 初始化一個事務。在有新數據到達并且當前事務為空時調用。

  • preCommit: 預提交數據,即不再寫入當前事務并準好提交當前事務。在 sink 算子進行快照的時候調用。

  • commit: 正式提交數據,將準備好的事務提交。在作業的 checkpoint 完成時調用。

  • abort: 放棄事務。在作業 checkpoint 失敗的時候調用。

下面以 Bucketing File Sink 作為例子來說明如何基于異步 checkpoint 來實現事務性 sink。
Bucketing File Sink 是 Flink 提供的一個 FileSystem Connector,用于將數據流寫到固定大小的文件里。  Bucketing File Sink 將文件分為三種狀態,in-progress/pending/committed,分別表示正在寫的文件、寫完準備提交的文件和已經提交的文件。
Flink Exactly-Once 投遞的實現淺析是怎樣的
運行時,Bucketing File Sink 首先會打開一個臨時文件并不斷地將收到的數據寫入(相當于事務的 beginTransaction 步驟),這時文件處于 in-progress。  直到這個文件因為大小超過閾值或者一段時間內沒有新數據寫入,這時文件關閉并變為 pending 狀態(相當于事務的 pre-commit 步驟)。  由于 Flink checkpoint 是異步的,可能有多個并發的 checkpoint,Bucketing File Sink 會記錄 pending 文件對應的 checkpoint epoch,當某個 epoch 的 checkpoint 完成后,Bucketing File Sink 會收到 callback 并將對應的文件改為 committed 狀態。  這是通過原子操作重命名來完成的,因此可以保證 pre-commit 的事務要么 commit 成功要么 commit 失敗,不會出現其他中間狀態。
Commit 出現錯誤會導致作業自動重啟,重啟后 Bucketing File Sink 本身已被恢復為上次 checkpoint 時的狀態,不過仍需要將文件系統的狀態也恢復以保證一致性。  從 checkpoint 恢復后對應的事務會再次重試 commit,它會將記錄的 pending 文件改為 committed 狀態,記錄的 in-progress 文件 truncate 到 checkpoint 記錄下來的 offset,而其余未被記錄的 pending 文件和 in-progress 文件都將被刪除。
上面主要圍繞事務保證的 AC 兩點(Atomicity 和 Consistency),而在 I(Isolation)上 Flink exactly-once sink 也有不同的實現方式。  實際上由于 Flink 的流計算特性,當前事務的未 commit 數據是一直在積累的,根據緩存未 commit 數據的地方的不同,可以將事務性 sink 分為兩種實現方式。
  • 在 sink 端緩存未 commit 數據,等 checkpoint 完成以后將緩存的數據 flush 到下游。這種方式可以提供 read-committed 的事務隔離級別,但同時由于未 commit 的數據不會發往下游(與 checkpoint 同步),sink 端緩存會帶來一定的延遲,相當于退化為與 checkpoint 同步的 micro-batching 模式。

  • 在下游系統緩存未 commit 數據,等 checkpoint 完成后通知下游 commit。這樣的好處是數據是流式發往下游的,不會在每次 checkpoint 完成后出現網絡 IO 的高峰,并且事務隔離級別可以由下游設置,下游可以選擇低延遲弱一致性的 read-uncommitted 或高延遲強一致性的 read-committed。

在 Bucketing File Sink 的例子中,處于 in-progress 和 pending 狀態的文件默認情況下都是隱藏文件(在實踐中是使用下劃線作為文件名前綴,HDFS 的 FileInputFormat 會將其過濾掉),只有 commit 成功后文件才對用戶是可見的,即提供了 read-committed 的事務隔離性。理想的情況下 exactly-once sink 都應該使用在下游系統緩存未 commit 數據的方式,因為這最為符合流式計算的理念。最為典型的是下游系統本來就支持事務,那么未 commit 的數據很自然地就是緩存在下游系統的,否則 sink 可以選擇像上例的 Bucketing File Sink 一樣在下游系統的用戶層面實現自己的事務,或者 fallback 到等待數據變為 committed 再發出的 micro-batching 模式。

總結

Exactly-once 是實時系統最為關鍵的準確性要求,也是當前限制大部分分布式實時系統應用到準確性要求更高的業務場景(比如在線事務處理 OLTP)的問題之一。  目前來說流式計算的 exactly-once 在理論上已經有了很大的突破,而 Flink 社區也在積極汲取最先進的思想和實踐經驗。  隨著 Flink 在 exactly-once 上的技術愈發成熟,結合 Flink 本身的流處理特性,相信在不遠的將來,除了構造數據分析、數據管道應用, Flink 也可以在微服務領域占有一席之地。

上述就是小編為大家分享的Flink Exactly-Once 投遞的實現淺析是怎樣的了,如果剛好有類似的疑惑,不妨參照上述分析進行理解。如果想知道更多相關知識,歡迎關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

嘉鱼县| 新竹市| 从化市| 天全县| 锦屏县| 神农架林区| 龙南县| 嘉义市| 浦县| 静乐县| 威信县| 荣成市| 天水市| 海南省| 平凉市| 香河县| 六盘水市| 奎屯市| 沽源县| 汝阳县| 六安市| 万安县| 莲花县| 长沙县| 绥化市| 调兵山市| 屏南县| 井陉县| 涞源县| 雷波县| 沾益县| 凤阳县| 吉木乃县| 马关县| 兴和县| 绥滨县| 三原县| 松阳县| 吉隆县| 明星| 新泰市|