1. 程式人生 > >Flink流處理(二)- 時間語義

Flink流處理(二)- 時間語義

嚴重 結果 rep 通知 ble eager 自動 行處理 應該

4. 時間語義(Time Semantics

這章我們會介紹時間語義,以及在流中,對於時間的各種不同的概念的描述。同時我們也會討論一個流處理器在事件亂序的情況下,如何能提供精準的結果,以及如何使用流對歷史events進行處理。

一分鐘的含義

假設我們要持續的對流計算並生成結果,例如每一分鐘。這裏的“一分鐘”在流處理應用裏到底意味著什麽呢?

考慮這麽一個場景,一個程序用於分析手機網遊用戶的events。用戶屬於各個小隊。基於小隊成員達成遊戲給定目標的速度,應用收集小隊的信息並在遊戲中給出獎勵,例如升級、經驗等。例如,如果一個小隊的所有用戶在一分鐘內生產了500個泡泡,則他們獲得一次升級。小明是其中一個玩家,他每天早上會在去上班的公交上玩這個遊戲。可問題是,小明住在大山裏,在出山的路上網絡特別差。假設小明開始在遊戲中生產泡泡,此時手機連接到了網絡,並發送events到分析程序。突然,公交進入了一個隧道,導致他的手機斷網了。小明繼續玩遊戲,此時events會緩存到他的手機裏。當公交出了隧道,網絡恢復後,pending的events會被發送到分析程序。此時分析程序怎麽做?在這裏一分鐘意味著什麽呢?是否考慮到了小明斷網的時間?下圖描述了此問題:

技術分享圖片

在線遊戲是一個簡單的場景,描述了 operator 語義如何依賴於時間。當events發生在某個時間段內,但是應用接收到events時已超過了這個時間段時,應用應如何處理時間語義?在這個手機遊戲中,若是對此處理不當,會導致較差的客戶體驗。但是在一些非常看重時間的應用中,結果可能會更嚴重。如果僅考慮在一分鐘內接收到多少個events,則結果會直接與於網絡連接狀況、或是處理速度等相關。所以,真正定義一分鐘內的events時,應該與數據本身的時間相關。

例如在小明玩遊戲這個例子中,流處理應用可以以兩種時間概念進行操作:處理時間(processing time)或事件時間(event time)。接下來介紹這兩種概念。

處理時間(Processing Time

處理時間是處理流的operator在執行時,所屬機器上的本地時間。Processing-time 窗口包含所有在一個時間周期內到達window operator 的events,以本地機器時間衡量。如下圖所示,在小明遊戲的案例中,在小明的手機斷開連接後,processing-time 窗口仍會持續計時,所以不會將小明斷網時間內的events計入到當前時間段。

技術分享圖片

事件時間(Event Time

事件時間是一個event實際發生的時間,它基於事件流中event被打上的時間戳。時間戳一般存儲與event 數據中。下圖展示了一個event-time 窗口,可以正確的將events放入合適的窗口中,反應了事件實際發生的情況,即使事件的到達存在延遲。

技術分享圖片

事件時間將處理速度與結果完全解耦。基於事件時間的操作時可預測的(predictable)並且結果是明確的(deterministic)。使用事件時間窗口計算時,無論流處理的速度有多快,或是events到達operator的速度有多慢,它輸出的一定是個相同的結果。

處理延遲的events僅僅是事件時間可以解決的眾多問題中的一個。更普遍的數據亂序的問題,也可以由事件時間解決。假設小花是遊戲的另一個玩家,她與小明都是做的同一班公交,在同一時間玩遊戲,但是用的是不同的手機卡。在過隧道時,小明的手機沒信號了,但是小花的手機還可以正常聯網並向遊戲應用繼續發送events。

依賴於事件時間,我們可以在數據無序到達的情況下,依然保證事件的正確性。進一步的說,在結合了可重跑的流(replayable streams)時,明確的時間戳可以用於快速執行過去的數據(fast forward the past)。也就是說,你可以重跑(replay) 一個流並分析歷史數據,就像events是實時發生的一樣。同時,你也可以快進計算,直到到達當前的狀態(fast forward the computation to the present),這樣一旦應用獲取了正在發生的事件時,它可以像一個實時應用一樣,以同樣的program logic繼續工作。

水印(Watermarks

在討論event-time 窗口時,我們忽略了一個很重要的方面:我們如何決定何時觸發一個event-time 窗口?也就是說,我們需要等待多長時間,才能確保已經收到了在某個特定時間點之前發生的所有事件呢?並且我們如何知道數據會有延遲呢?很遺憾,這些問題是沒有一個完美的答案的,因為分布式系統會有各種預料之外的異常,並且可能會有多方面的外部組件影響延遲。在這章我們會引入如何使用水印(watermarks)配置event-time窗口的行為。

水印是一個全局的進度指標(progress metric),表示的是:在什麽時間點,我們可以有信心判斷,之後不會有更多的(延遲的)事件到達。本質上,水印提供了一個邏輯時鐘,提醒系統關於當前event time的信息。當一個operator收到了一個水印,時間為T。它可以假設:不會再有更多時間戳小於T的事件被收到。水印對於event-time窗口以及operators處理亂序events至關重要。一旦一個水印被接收到後,operators即被通知到:對於某個時間周期,所有的時間戳已經被觀察到(observed),接下來應觸發計算,或是將收到的事件進行排序。

水印提供了一個配置,用於權衡結果可信度與延遲。Eager watermarks可以確保低延遲,但是提供較低的可信度。在這種情況下,延遲的events可能會在水印之後到達,我們需要提供處理這些events的代碼。另一方面,如果水印特別寬松,則我們對結果的準確度會有更大的信心,但是可能會增加不必要的處理延遲。

在很多真實應用中,系統並沒有足夠的知識去完美地準確算出水印。在手機遊戲的例子中,基本是不可能預測用戶會有多長的時間丟失連接。無論是自定義的水印或是自動生成的水印,在分布式系統中,由於有落後的tasks,跟蹤整個分布式系統的進度可能仍是個問題。所以,如果僅簡單的依賴於水印,則可能並不是一個很好的方法。更重要的是,流處理系統應提供一些機制去處理這些落後於水印的events。根據應用的需求,可以簡單的丟棄這些事件,或是記錄日誌,亦或是使用它們去修正之前的結果。

處理時間vs事件時間

這裏你可能會好奇既然event time可以解決我們所有的問題,那為什麽還要提出processing time。事實上,處理時間在某些情況下是非常有用的。Processing-time 窗口可以盡可能地引入最低延時。例如:不考慮延遲及亂序事件,window僅是用於緩存一些數據,在到達一段時間後立即觸發一個計算。所以對於那些速度比準確度更重要的應用來說,processing time 會更方便。另一個案例是定期實時提供報告結果,不考慮精準度。最後,processing-time窗口是流自身行為的一個體現,可能在某些場景下是一個很好的屬性。例如,計算每秒收集到的事件,用於檢測outage。總而言之,processing time 提供了低延時,但是輸出的結果取決於處理的速度,並且結果並不是明確的。而event time保證了明確的結果,並可以處理延時或亂序的事件。

References

Vasiliki Kalavri, Fabian Hueske. Stream Processing With Apache Flink. 2019

Flink流處理(二)- 時間語義