Flink 六脈神劍祕訣

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消息隊列位移

有了狀態跟時間,那麼Flink是怎麼進行容錯處理的呢?下面我們仔細介紹

  1. 首先對於每個增量計算過程中,需要有快照保存類似timer、connector、window、state等信息 --- 該部分可以理解爲信息保存,也就是Checkpoint -- 檢查點
  2. 既然有了檢查點,如何實現呢?
    1. 由於Flink的語法會被抽象爲DAG(有向無環圖),在次過程中,由source端會下發一個叫barrier的數據標誌
    2. barrier會將source下發的數據,分到不同的checkpoint中
    3. 如果是exactly_once語義,那麼會需要進行barrier對齊,保證結果一致性
    4. 對齊之後進行checkpoint,生成snapshot,進行持久化存儲
    5. 完成snapshot之後,下發barrier直至sink,表明此次快照結束
  3. 針對Checkpoint而言,有兩種模式
    • at_least_once語義:即事件消息至少被消費一次
      • 對於 at_least_once,消息在經過各個operator時,不會進行堵塞,而是來了一份數據消費一份,進行快照
    • exactly_once語義:事件消息僅被消費一次
      • 對於消費一次而言,當其他barrier在算子端未對齊的時候,消息不被消費,而是被緩存進barrierbuff,等到barrier對齊之後,數據從barrierbuff中被消費,因此該語義也會造成比較大的延時
  4. 當任務在某個點fail之後,我們進行重啓,比如我們重啓9點的數據,進行計算,但是在flink內部,如果9點沒有相應的checkpoint,那麼會向前找最近的一個點,比如8.59分這種

Flink查詢

  • 對於流計算而言,數據查詢是動態的,是持續查詢。原因是因爲每個時刻數據內容都在發生改變,那麼流數據是如何做到結果一致性的呢?
  • 接下來我們以Mysql的存儲過程舉例,說明Flink的持續查詢是如何實現
    • Mysql的任何操作都會被記錄在binlog中,將binlog轉爲中繼日誌可以實現備份的功能。我們也可以利用該日誌來模型持續查詢
    • 我們可以寫一個觸發器,一旦有新的數據進來之後,就進行查詢。然後通過一條條的數據插入,對應會有一次次的查詢結果
    • 對於無PK(主鍵)的表而言,事實上實現的是append
    • 對於有PK的表而言,實現的是update,但是Mysql
    • 需要注意:Mysql實現的是全量查詢,而在Flink中實現的是增量查詢Flink的持續查詢也可以這樣理解,當有一條數據來的時候Flink會進行一次查詢,數據流源源不斷,查詢結果也會不斷刷新,這個過程就是Flink的持續查詢

Flink中文文檔

https://flink.apachecn.org/#/

後續會更新flink的相關優化技巧,畢竟未來流是主要方向

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