非確定性演算法 詳解 Flink 實時應用的確定性

2021-10-12 07:56:13 字數 4050 閱讀 9978

確定性(determinism)是電腦科學中十分重要的特性,確定性的演算法保證對於給定相同的輸入總是產生相同的輸出。在分布式實時計算領域,確定性是業界一直難以解決的課題,由此導致用離線計算修正實時計算結果的 lambda 架構成為大資料領域過去近十年的主流架構。

而在最近幾年隨著 google the dataflow model 的提出,實時計算和離線計算的關係逐漸清晰,在實時計算中提供與離線計算一致的確定性成為可能。本文將基於流行實時計算引擎 apache flink,梳理構建乙個確定性的實時應用要滿足什麼條件。

比起確定性,準確性(accuracy)可能是我們接觸更多的近義詞,大多數場景下兩者可以混用,但其實它們稍有不同: 準確的東西一定是確定的,但確定性的東西未必百分百準確。在大資料領域,不少演算法可以根據需求調整成本和準確性的平衡,比如 hyperloglog 去重統計演算法給出的結果是有一定誤差的(因此不是準確的),但卻同時是確定性的(重算可以得到相同結果)。

要分割槽確定性和準確性的緣故是,準確性與具體的業務邏輯緊密耦合難以評估,而確定性則是通用的需求(除去少數場景使用者故意使用非確定性的演算法)。當乙個 flink 實時應用提供確定性,意味著它在異常場景的自動重試或者手動重流資料的情況下,都能像離線作業一般產出相同的結果,這將很大程度上提高使用者的信任度。

常見的投遞語義有 at-most-once、at-least-once 和 exactly-once 三種。嚴格來說只有 exactly-once 滿足確定性的要求,但如果整個業務邏輯是冪等的, 基於 at-least-once 也可以達到結果的確定性。

實時計算的 exactly-once 通常指端到端的 exactly-once,保證輸出到下游系統的資料和上游的資料是一致的,沒有重複計算或者資料丟失。要達到這點,需要分別實現讀取資料源(source 端)的 exactly-once、計算的 exactly-once 和輸出到下游系統(sink 端)的 exactly-once。

其中前面兩個都比較好保證,因為 flink 應用出現異常會自動恢復至最近乙個成功 checkpoint,pull-based 的 source 的狀態和 flink 內部計算的狀態都會自動回滾到快照時間點,而問題在於 push-based 的 sink 端。sink 端是否能順利回滾依賴於外部系統的特性,通常來說需要外部系統支援事務,然而不少大資料元件對事務的支援並不是很好,即使是實時計算最常用的 kafka 也直到 2017 年的 0.11 版本才支援事務,更多的元件需要依賴各種 trick 來達到某種場景下的 exactly-once。

總體來說這些 trick 可以分為兩大類:

為了保證 flink 應用的確定性,在選用官方 connector,特別是 sink connector 時,使用者應該留意官方文件關於 connector 投遞語義的說明[3]。此外,在實現定製化的 sink connector 時也需要明確達到何種投遞語義,可以參考利用外部系統的事務、寫操作的冪等性或預寫日誌三種方式達到 exactly-once 語義。

函式***是指使用者函式對外界造成了計算框架意料之外的影響。比如典型的是在乙個 map 函式裡將中間結果寫到資料庫,如果 flink 作業異常自動重啟,那麼資料可能被寫兩遍,導致不確定性。對於這種情況,flink 提供了基於 checkpoint 的兩階段提交的鉤子(checkpointedfunction 和 checkpointlistener),使用者可以用它來實現事務,以消除***的不確定性。另外還有一種常見的情況是,使用者使用本地檔案來儲存臨時資料,這些資料在 task 重新排程的時候很可能丟失。其他的場景或許還有很多,總而言之,如果需要在使用者函式裡改變外部系統的狀態,請確保 flink 對這些操作是知情的(比如用 state api 記錄狀態,設定 checkpoint 鉤子)。

在演算法中引入當前時間作為引數是常見的操作,但在實時計算中引入當前系統時間,即 processing time,是造成不確定性的最常見也最難避免的原因。對 processing 的引用可以是很明顯、有完善文件標註的,比如 flink 的 time characteristic,但也可能是完全出乎使用者意料的,比如**於快取等常用的技術。為此,筆者總結了幾類常見的 processing time 引用:

綜合來講,要完全避免 processing time 造成的影響是非常困難的,不過輕微的不確定性對於業務來說通常是可以接受的,我們要做的更多是提前預料到可能的影響,保證不確定性在可控範圍內。

watermark 作為計算 event time 的機制,其中乙個很重要的用途是決定實時計算何時要輸出計算結果,類似檔案結束標誌符(eof)在離線批計算中達到的效果。然而,在輸出結果之後可能還會有遲到的資料到達,這稱為視窗完整性問題(window completeness)。

視窗完整性問題無法避免,應對辦法是要麼更新計算結果,要麼丟棄這部分資料。因為離線場景延遲容忍度較大,離線作業可以推遲一定時間開始,盡可能地將延遲資料納入計算。而實時場景對延遲有比較高的要求,因此一般是輸出結果後讓狀態儲存一段時間,在這段時間內根據遲到資料持續更新結果(即 allowed lateness),此後將資料丟棄。因為定位,實時計算天然可能出現更多被丟棄的遲到資料,這將和 watermark 的生成演算法緊密相關。

雖然 watermark 的生成是流式的,但 watermark 的下發是斷點式的。flink 的 watermark 下發策略有 periodic 和 punctuated 兩種,前者基於 processing time 定時觸發,後者根據資料流中的特殊訊息觸發。

periodic watermark 正常狀態與重放追資料狀態

periodic watermark 正常狀態與重放追資料狀態

基於 processing time 的 periodic watermark 具有不確定。在平時流量平穩的時候 watermark 的提公升可能是階梯式的(見圖1(a));然而在重放歷史資料的情況下,相同長度的系統時間內處理的資料量可能會大很多(見圖1(b)),並且伴有 event time 傾斜(即有的 source 的 event time 明顯比其他要快或慢,導致取最小值的總體 watermark 被慢 watermark 拖慢),導致本來丟棄的遲到資料,現在變為 allowed lateness 之內的資料(見圖1中紅色元素)。

punctuated watermark 正常狀態與重放追資料狀態

punctuated watermark 正常狀態與重放追資料狀態

相比之下 punctuated watermark 更為穩定,無論在正常情況(見圖2(a))還是在重放資料的情況(見圖2(b))下,下發的 watermark 都是一致的,不過依然有 event time 傾斜的風險。對於這點,flink 社群起草了 flip-27 來處理[4]。基本原理是 source 節點會選擇性地消費或阻塞某個 partition/shard,讓總體的 event time 保持接近。

綜上所述,watermark 目前是很難做到非常確定的,但因為 watermark 的不確定性是通過丟棄遲到資料導致計算結果的不確定性的,只要沒有丟棄遲到資料,無論中間 watermark 的變化如何,最終的結果都是相同的。

確定性不足是阻礙實時計算在關鍵業務應用的主要因素,不過當前業界已經具備了解決問題的理論基礎,剩下的更多是計算框架後續迭代和工程實踐上的問題。就目前開發 flink 實時應用而言,需要注意投遞語義、函式***、processing time 和 watermark 這幾點造成的不確定性。

參考:flux capacitor, huh? temporal tables and joins in streaming sql

flink-12005 event time support

fault tolerance guarantees of data sources and sinks

flip-27: refactor source inte***ce

[flink-5601] window operator does not checkpoint watermarks

作者介紹:

林小鉑,網易遊戲高階開發工程師,負責遊戲資料中心實時平台的開發及運維工作,目前專注於 apache flink 的開發及應用。**問題本來就是一種樂趣。

比較Sherwood演算法與確定性演算法

實驗題目 寫一sherwood演算法c,與演算法a,b,d比較,給出實驗結果 演算法的思想很簡單,因為經過計算,演算法b是從val前 這裡給出演算法a b c d homework p67.cpp 此檔案包含 main 函式。程式執行將在此處開始並結束。include pch.h include i...

RL(十四)深度確定性策略梯度演算法

前面我們講了深度強化學習,雖然強化學習和深度學習得到了乙個很好的結合,但是他們在實際的使用中還是有一些限制的,比如演算法模型容易過估計 無法處理連續動作控制任務。尤其是無法使用連續動作這個缺點,極大的限制了dqn的使用。所以本節就來學習可以處理連續動作的深度確定性策略梯度演算法 ddpg 下面按著策...

編譯原理 非確定性的自上而下分析法

設有文法 g s g s g s 輸入串 w a dbw adb w ad b 是否為文法 g s g s g s 中的乙個句子?1 首先讓輸入流指標指向輸入串的第乙個符號 a aa 文法的開始符號 s ss 作為根結點,用 s ss 的規則構造語法樹,a aa 與 s ss 的第乙個子結點匹配。2...