1. 程式人生 > >Flink流處理過程的部分原理分析

Flink流處理過程的部分原理分析

文章目錄

前言


在分散式領域,計算和儲存一直是兩大子領域。很多分散式理念在計算和儲存的實現中會有著完全不同的邏輯,比如我們快照,計算框架中的快照和我們平常說的儲存快照實現不同點在於哪裡呢?筆者做為一個研究儲存模組出身的人,最近在研讀Flink流處理的部分原理,小小作番總結。很多時候,以儲存的眼光來看待計算過程中的處理過程,還是有很多不一樣的地方的。下文中,筆者將逐一介紹Flink流處理的一些過程分析。額外說明一點,以下內容來源於早期Flink內部設計文件,可能與現今使用的Flink有所差異,詳細來源可見文末引用地址。

流的時間有序性保證


在上一篇闡述Flink視窗處理的文章中,筆者提到了關於網路傳輸等外部因素造成的流資料的潛在亂序問題,也就是一些“遲到“了的資料。對於這種情況,Flink在內部提供了一種有序資料流的概念,當然這個有序流是一種被二次加工過的資料流,從而保證了其有序性。那麼問題來了,這種資料流是進行了何種處理方式呢?

用一句簡單地話來說:通過watermark對資料重排序,來保證整體資料流的有序性

而這裡分段資料的重排序,依靠的是資料流的watermark值。每當我們每接收到一份資料到buffer中時,我們選定其中最新的watermark值,對buffer裡資料的時間小於此watermark值的資料在buffer中做一個排序。然後將此排序好的資料發向下游

。這裡基於的一個原則是:時間比當前watermark訊息早的資料都已經到來了,所以我們可以大膽地把這批資料先拍好序再發出去。圖示效果如下:

在這裡插入圖片描述

視窗序列對齊


最Flink流任務中,會涉及到資料被多次視窗處理的問題,比如資料流被A視窗處理過有到看B視窗中做處理。我們如何來指定視窗的序列關係呢?

這裡Flink採用了一種視窗逐一對齊的做法。後一視窗的起始末尾邊界與前一序處理視窗的邊界完全對齊,對應區間範圍內的結果資料同樣落位到相對應的區間視窗內。如下圖所示:

在這裡插入圖片描述

流資料的容錯:Checkpoint機制


流處理與批處理相比,它的一大優勢在於它的低延時,而批處理的一個得天獨厚的優勢是錯誤恢復容易。因為批處理任務在每次的批處理操作中會儲存住全部的輸入資料,如果出現結果算錯的情況,重新執行一次處理過程即可。而流式計算中連續不斷的資料處理,使得錯誤恢復變得複雜起來。所以假如流處理任務能夠做到快速的錯誤恢復,那麼其可用性將會大大加強。下面筆者主要闡述的是Flink的錯誤恢復機制:Checkpoint機制。

首先,我們假設發生了一個流處理任務執行異常失敗的場景,然後我們準備在下一刻進行完全地恢復,重新回到失敗的那個時刻點,任務繼續往後跑。那麼在這裡我們至少有保留哪些狀態資料呢?答案是以下3點:

  • Source的偏移量位置
  • 當時正在流動中的資料
  • 操作狀態資料

下面我們來看看針對這2類資料,Flink內部是如何做定期checkpoint的。

Barrier


Flink為了實現定期的checkpoint,做的一個核心改動是在流資料中增加一個標記資料記錄,名為stream barrier。不同時間點插入barrier資料將流資料分隔成了多份,每份對應一次checkpoint操作,同時checkpoint會保留住資料來源source當時的偏移量資訊。如下圖所示:

在這裡插入圖片描述

當barrier標記從source流向到sink下游,並且系統受到sink端的確認訊息後,此checkpoint宣告正式完成。如果過程中需要涉及多input的輸入時,處理快的barrier流會在過程中等待落後的其它流直到它們的barrier資訊到來,然後再往下游傳輸資料,如下圖:

在這裡插入圖片描述

State


對於應用中所涉及的中間狀態資料,Flink支援使用者自定義狀態持久化操作,然後應用程式在重新啟動的時候從外部儲存中重新恢復狀態資料。

一般情況下,為了保證狀態資料的一致性,checkpoint狀態資料的時候是同步的過程。Flink在後來實現了一種非同步狀態同步的方法,主要採用的思路是拷貝原狀態的資料,然後用非同步執行緒去持久化拷貝的那份狀態資料。同時為了防止每次checkpoint大量相同狀態的資料,Flink在後期也實現了增量checkpoint的功能。

引用


[1].https://cwiki.apache.org/confluence/display/FLINK/Time+and+Order+in+Streams
[2].https://ci.apache.org/projects/flink/flink-docs-master/internals/stream_checkpointing.html