Flink 基礎#
內容參考自:
有狀態流式處理#
概念#
傳統批次處理:持續收集數據,以時間作為批次劃分的依據,周期性執行批次運算,這樣可能存在的場景問題:
- 假如一個小時作為一個批次劃分的依據,需要統計特定事件轉換次數,開始轉換發生在第 58 分鐘,結束轉換在下一個小時的第 7 分鐘,那麼如何完成跨批次的數據統計?
- 數據從產生到被接收中間耗時不一定,可能某個事件發生早於 A,但到達時間晚於 A,如何處理這種接收到的時間順序顛倒問題?
理想方法就是:
- 引入
狀態(State)
機制,可以累積狀態和維護狀態,累積狀態代表著過去歷史中接受過的所有歷史事件,對輸出結果有影響 Time時間機制
: 有機制可以做到對數據完整性的操作,比如設定只有某個時間段上的數據全部都接收到後,再計算輸出結果
這就是所謂的有狀態流式處理
有狀態流式處理的挑戰#
- 狀態容錯 (State Fault Tolerance):
- 狀態維護 (State Management):
- Event-time 處理 (Event-time processing):
- 狀態保存與遷移 (Savepoints and Job Migration):
狀態容錯#
簡單場景的精確一次 (Exactly-once) 容錯保證:
無限流的數據進入,但後面是單一 Process 的計算,這種情況下如果要確保 Process 產生精確一次的狀態容錯,每處理完一筆數據,更改完狀態後進行一次快照,快照包含在隊列中並與相應的狀態進行對比,完成一致的快照,就能確保精確一次
分佈式狀態容錯#
-
在分佈式場景中,多個節點計算進行本地狀態的修改,但只產生一個
Global consistent snapshot
(全域一致性的快照) -
基於
checkpoint
檢查點機制進行容錯恢復 -
基於
simple lamport
演算法機制的延伸實現分佈式快照
,Flink 可以做到再不中斷計算的狀態下持續完成Global consistent snapshot
(全域一致性的快照)。大致方法就是 Flink 會在數據流中插入 checkpoint barrier 標誌位,後續的 Operator 在數據流中收到 checkpoint barrier N 後就會將自己的狀態保存,這樣從最開始的數據源到計算完成後都建立了這次的 checkpoint 保存狀態,後面還有 checkpoint barrier N+1、N+2 也同時在數據流中同步進行,這樣就可以做到在不阻擋運算的狀況下持續產生 Checkpoint
狀態維護#
Flink 目前支持的方式有:
-
JVM Heap存儲狀態
: 適合狀態量不大的情況下,因為直接存儲在 JVM heap 上,當需要讀取狀態時,是直接用 Java object 進行的讀寫,不需要序列化。但當 Checkpoint 需要將每一個運算值的本地狀態放入 Distributed Snapshots 的時候,就需要進行序列化了 -
RocksDB存儲狀態
: 一種 out of core 的狀態後端。在 Runtime 的本地狀態後端讓使用者去讀取狀態的時候會經過磁碟,相當於將狀態維護在磁碟裡,與之對應的代價可能就是每次讀取狀態時,都需要經過序列化和反序列化的過程,性能可能相對來說差一點
Event-time 處理#
處理時間(Processing Time)
: Process Time 相當於事件到達然後開始進行處理的時間,是不一定的,比如網路原因這個時間都會變化事件時間(Event Time)
: Event Time 就是事件實際發生的時間,根據每一條處理記錄所攜帶的時間戳來判定,這個是唯一且不變的接入時間(Ingestion Time)
: 是指事件在 source 運算符中進入 Flink 數據流的時間
對比
- Processing Time 處理起來更加的簡單,而 Event Time 要更麻煩一些
- 使用 Processing Time 的時候,我們得到的處理結果(或者說流處理應用的內部狀態)是不確定的。而因為 Flink 內部對 Event Time 做了各種保障,使用 Event Time 的情況下,無論重放數據多少次,都能得到一個相對確定可重現的結果
- 判斷應該使用 Processing Time 還是 Event Time 的時候,可以遵循一個原則:當你的應用遇到某些問題要從上一个 checkpoint 或者 savepoint 進行重放,是不是希望結果完全相同。如果希望結果完全相同,就只能用 Event Time;如果接受結果不同,則可以用 Processing Time。Processing Time 的一個常見的用途是,我們要根據現實時間來統計整個系統的吞吐,比如要計算現實時間一個小時處理了多少條數據,這種情況只能使用 Processing Time
參考鏈接
狀態保存與遷移#
基於 Savepoint 機制實現,Savepoint 跟 checkpoint 類似,不同在於 Savepoint 是手動觸發用於全局狀態保存的,具體參考鏈接:
Flink 實時計算 - 深入理解 Checkpoint 和 Savepoint
Flink 基本概念#
-
Streams
: 流,分為有限數據流與無限數據流,unbounded stream
是有始無終的數據流,即無限數據流;而bounded stream
是限定大小的有始有終的數據集合,即有限數據流,二者的區別在於無限數據流的數據會隨時間的推演而持續增加,計算持續進行且不存在結束的狀態,相對的有限數據流數據大小固定,計算最終會完成並處於結束的狀態。 -
State
: 狀態是計算過程中的數據信息,在容錯恢復和 Checkpoint 中有重要的作用,流計算在本質上是 Incremental Processing,因此需要不斷查詢保持狀態;另外,為了確保 Exactly- once 語義,需要數據能夠寫入到狀態中;而持久化存儲,能夠保證在整個分佈式系統運行失敗或者掛掉的情況下做到 Exactly- once,這是狀態的另外一個價值。 -
Time
: 分為Event time
、Ingestion time
、Processing time
,Flink 的無限數據流是一個持續的過程,時間是我們判斷業務狀態是否滯後,數據處理是否及時的重要依據。 -
API
: API 通常分為三層,由上而下可分為SQL / Table API
、DataStream API
、ProcessFunction
三層,API 的表達能力及業務抽象能力都非常強大,但越接近 SQL 層,表達能力會逐步減弱,抽象能力會增強,反之,ProcessFunction 層 API 的表達能力非常強,可以進行多種靈活方便的操作,但抽象能力也相對越小
Flink Window#
- 以事件數量驅動的 Count Window
- 以會話間隔驅動的 Session Window
- 以時間驅動的 Time Window