Flink是什麼?
Flink是一款實時計算框架,能夠實現ms級別甚至更低的延時計算(流式處理 -- 有狀態的計算處理),不少同學肯定會提及spark streaming(可認爲是批處理,類似Hive -- 無狀態計算;這幾個框架只能做到準實時,ms級別的延時是達不到要求)。當然,如果你對延時容忍度高,那麼可以選擇這兩個框架
最具代表性的使用場景:阿里雙11大屏交易總金額的實時刷新
Flink如何實現流式處理?
對於批處理而言,當前提條件限制之後,數據的輸入是固定的;並且,在執行一次計算計劃的時候,要麼全部成功或者失敗。
對於流處理而言,數據如流水一般由源頭奔湧向下。那麼通過什麼準則去如何去抽取、約定你需要的數據呢?-----時間。更重要的是,由於流式計算中間也會遇到宕機、數據處理失敗等等問題,時間點也能作爲恢復範圍點重要參考
在Flink中有三個時間定義
- Event time:事件本身發生的時間,與flink引擎無關。例如:用戶在某個時刻下單一個商品,訂單產生時間是事件時間
- Processing Time:Flink處理數據時間
- Ingestion Time:進入Flink框架時間。例如:訂單產生在9:00,那麼9:00是Event time;數據在9:00 30s時進入flink中(如果有較大延時),那麼9:00 30s這個時刻是Ingestion Time,然後數據在9:01被計算,9:01是Processing Time
Flink如何應對延時?
- 延時產生原因:網絡抖動、計算資源不夠等一系列的原因,會導致在整個流處理過程中有較大的延時
- 延時影響:可能導致部分計算結果不準確
- 例如:我們用長度爲1h 的時間窗口 計算 9:00 -- 10:00 交易累計金額。在9:59 40s的時候確實產生了一條交易數據,那麼該條數據的事件時間是 9:59 40s。由於延時的問題,導致該條數據在 10:01 才被Flink讀取,因此該數據未能被計算(不在9:00 -10:00 窗口範圍內);一般在流計算的時候會進行批計算,在覈對結果的時候就會發現總金額少了 9:59 40s 這份數據
- 如何處理延時:watermark (水位)
- watermark:基於event time,告訴窗口函數,可能有數據還沒有來,你再等一等執行計算
- watermark影響:但是watermark設置的越大,會帶來更大的延時,效果會越準確(最後可理解爲轉成了批處理?) ,具體根據業務場景來
- 處理延時:在進行計算之前,設置一個水位點,例如設置2min。還是看上面的例子,假如不設水位那麼 9:59 40s 的數據必然會丟,那麼設置會怎麼樣呢?
- 設置2min之後,在10:00 窗口觸發時間,窗口函數不會立馬觸發,而是會再等 2min,等到10:02觸發窗口計算。然後看這兩分鐘內是否還會有event time 在窗口內的數據(這段話細品、你細品)。因此,儘管9:59 40s 延時到 10:01 ,但是10:01 < 10:02 因此該條數據不會丟
Flink窗口函數(主要講複雜事件處理cep)
- 滑動窗口
- 滾動窗口
- 會話窗口
- cep機制(Complex event processing) -- 複雜事件處理:可認爲是一種爲事件窗
- cep與前面三個窗口的區別在於:前面三個窗口是基於時間來處理流數據,而cep是根據事件定義來處理流數據。前面三個可以自行csdn 或者百度,都比較好理解,接下來主要講cep
- cep如何工作?
- 舉個例子:你開車從 A -> B點,然後你要計算這段行程中發生了哪些不良駕駛行爲,如急加速、減速等(如果有埋點數據次採集的話)。但是在這裏你用不了時間窗口進行聚合累加,因爲你不知道 A->B點得用多久,不同人也不一樣。爲什麼cep可以?因爲cep可以將一個事件流定義爲一個窗口,如A->B,點火可以認爲是行程開始,熄火可以認爲是行程的結束,(這裏不是很嚴謹,肯定有很多愛開車的同學要跟我槓了,爲什麼不是從刷卡開始//手動狗頭)
- cep 完整定義
- 事件開始
- 中間事件
- 事件結束
- 通過上面事件定義,能夠將一個事件流從數據流從以窗口的方式剝離出來
Flink容錯
由於Flink是流式計算,整個計算過程不斷持續,區別於批計算(無狀態計算 --- 錯了整段重跑一次)。對於Flink而言,是增量計算,不可能全部重跑。一般都是在某個時間範圍內重跑,那麼就需要兩個條件。1、出錯的時間點,也就是你需要重跑的時間點 2、當時的計算狀態(state)
- 針對重跑時間
- 爲了保證數據的正確性,可以選擇在出錯時間點更提前的位置進行重跑(比如10點的時候數據報錯,你可以選擇在9點進行重跑),付出的代價就是需要去追數據。因爲現在可能是下午3點了,你從上午9點跑,這期間的數據都會被刷新一次,所以會考驗資源的一個配置,如果資源配置過低,很可能追不上現階段的數據,造成大延時。如果是追數據的話,建議整個資源配比調高一點
- 針對計算狀態(這裏面的東西很多)
- 爲什麼需要state,像之前提到的,Flink是增量計算,因此需要保存在計算過程中節點的中間計算結果或者元數據屬性,這兩塊統稱爲state。State可以分類兩大類
- keyState:進行group by的字段
- operatorState:讀取數據流的offest,類似於kafka消息隊列位移
- 爲什麼需要state,像之前提到的,Flink是增量計算,因此需要保存在計算過程中節點的中間計算結果或者元數據屬性,這兩塊統稱爲state。State可以分類兩大類
有了狀態跟時間,那麼Flink是怎麼進行容錯處理的呢?下面我們仔細介紹
- 首先對於每個增量計算過程中,需要有快照保存類似timer、connector、window、state等信息 --- 該部分可以理解爲信息保存,也就是Checkpoint -- 檢查點
- 既然有了檢查點,如何實現呢?
- 由於Flink的語法會被抽象爲DAG(有向無環圖),在次過程中,由source端會下發一個叫barrier的數據標誌
- barrier會將source下發的數據,分到不同的checkpoint中
- 如果是exactly_once語義,那麼會需要進行barrier對齊,保證結果一致性
- 對齊之後進行checkpoint,生成snapshot,進行持久化存儲
- 完成snapshot之後,下發barrier直至sink,表明此次快照結束
- 針對Checkpoint而言,有兩種模式
- at_least_once語義:即事件消息至少被消費一次
- 對於 at_least_once,消息在經過各個operator時,不會進行堵塞,而是來了一份數據消費一份,進行快照
- exactly_once語義:事件消息僅被消費一次
- 對於消費一次而言,當其他barrier在算子端未對齊的時候,消息不被消費,而是被緩存進barrierbuff,等到barrier對齊之後,數據從barrierbuff中被消費,因此該語義也會造成比較大的延時
- at_least_once語義:即事件消息至少被消費一次
- 當任務在某個點fail之後,我們進行重啓,比如我們重啓9點的數據,進行計算,但是在flink內部,如果9點沒有相應的checkpoint,那麼會向前找最近的一個點,比如8.59分這種
Flink查詢
- 對於流計算而言,數據查詢是動態的,是持續查詢。原因是因爲每個時刻數據內容都在發生改變,那麼流數據是如何做到結果一致性的呢?
- 接下來我們以Mysql的存儲過程舉例,說明Flink的持續查詢是如何實現
- Mysql的任何操作都會被記錄在binlog中,將binlog轉爲中繼日誌可以實現備份的功能。我們也可以利用該日誌來模型持續查詢
- 我們可以寫一個觸發器,一旦有新的數據進來之後,就進行查詢。然後通過一條條的數據插入,對應會有一次次的查詢結果
- 對於無PK(主鍵)的表而言,事實上實現的是append
- 對於有PK的表而言,實現的是update,但是Mysql
- 需要注意:Mysql實現的是全量查詢,而在Flink中實現的是增量查詢Flink的持續查詢也可以這樣理解,當有一條數據來的時候Flink會進行一次查詢,數據流源源不斷,查詢結果也會不斷刷新,這個過程就是Flink的持續查詢
Flink中文文檔
後續會更新flink的相關優化技巧,畢竟未來流是主要方向