Streaming System 第一章:Streaming 101

轉載自:https://yq.aliyun.com/articles/674448

簡介

Streaming101起源於在O'really上發表的兩篇博客,原文如下:
https://www.oreilly.com/ideas/the-world-beyond-batch-streaming-101
https://www.oreilly.com/ideas/the-world-beyond-batch-streaming-102
其中對流式計算的設計理念做了非常透徹的介紹。現存的系統如Flink/Spark Structured Streaming的設計理念都是出自於上述文章。後其作者又寫了一本介紹流計算原理的書《Streaming System》,更加詳細的介紹了流計算的基本概念及設計框架等。本文即爲其開篇第一章的概述。有志於深入研究流計算系統的讀者,可以詳細讀一下兩篇博客以及《Streaming System》原文,會大有毗益。

譯者才疏學淺,如有錯誤,歡迎指正。轉載請註明出處,侵權必究。

作爲一系列文章的第一篇,本文會從以下幾個方面入手,爲後續文章做好鋪墊。

  • 術語:需要精確的定義術語,才能更準確的描述複雜的問題,很多術語在目前討論流計算的文章重的含義都太寬泛,本文會嘗試爲這些術語下更精確的定義。
  • 能力:我會提出目前流計算系統的問題。爲了滿足現在用戶的需求,我認爲現在的數據處理系統應該採取的架構。
  • 時間域: 本文將介紹與數據處理相關的兩個主要時間域以及其關係,並指出這兩個時間域對數據處理系統的挑戰。

術語:什麼是流?

一說到流,很多文章中都會這樣描述:計算延時底但結果不準確,這是對流計算這個術語非常大的誤解。這些文章描述的都是現有流計算系統的特點,而不是‘流計算’本身。有良好設計的流計算系統,是完全能達到延時低並且結果準確的效果。因此本文及接下來一系列文章中中,‘流’特指:
__流計算系統__:能處理無界數據集的數據處理系統。

現實世界中,需要處理各種類型的數據。有兩個重要的(和正交的)維度定義了給定數據集的形狀:基數(cardinality)和構成(constitution)。

基數:描述了數據集的大小,有兩種精確的表達方式:

  • 有界數據:數據集大小固定
  • 無界數據:(理論上)數據集無限大
    其中如何處理無界數據,給數據處理系統帶來了新的挑戰。

構成:數據集的物理展現方式。兩種非常重要的構成方式如下:

  • 表:某個時間點上,所有數據的快照。現存的數據庫都是在處理表。
  • 流:隨時間變化的數據集,從每個元素(變化)的視角看,得到的視圖。基於MapReduce的系統都是在處理流。

被極度誇大的流處理的侷限性

本節會着重討論流系統的能力。之前很多針對流系統的論述都是低延時但是結果不精確,反之批處理才能提供精確的計算結果,這其實都是對流計算系統的誤解。經過良好的設計,流系統完全可以保證低延時,並且提供正確的結果。並且從理論上來說,流是批的超集。Flink根據這個理論實現了一個批流統一的計算引擎,並且批和流數據處理都是用流的方式實現的。爲了在處理能力上超越批,需要做好兩件事:

  • 正確性:使流的能力與批相同。
    保證流計算系統正確性的關鍵,是如何隨時將狀態進行持久化存儲。目前市面上很多流計算系統,還只能做到at-lease-once(至少一次)語義,根本不足以保證計算結果的準確。當然也有很多系統已經實現了exactley-once語義,從而保證結果的正確性。相關的論文有:FlinkMillWheel 如果有興趣,讀者可以仔細研讀下這些論文。
  • Tools for Reasoning about Time - 超越批
    如果數據在事件時間上亂序且無界,就需要能夠處理這種特點的數據的系統。目前的批處理系統很難做到這點。

接下來,首先會介紹以下時間域的基本概念,然後再深入看一下什麼是在事件時間上的亂序和無界數據。之後再探究批和流系統,如何處理有界和無界數據。

事件時間 vs. 處理時間

必須對時間域有深刻的瞭解,才能正確的理解無界數據處理的理論。目前,對所有數據處理系統來說,有兩個時間最關鍵:

  • 事件時間:事件發生的時間
  • 處理時間:事件流入系統的時間

理想世界裏,事件時間=處理時間。也就是事件一發生就會立即被處理。但是在現實事件中,這是不可能發生的。很多因素都會導致事件時間和處理時間不一致,例如:

  • 共享資源有限:網絡帶寬/CPU等限制
  • 軟件:分佈式系統限制
  • 數據本身的特性:比如主鍵分佈或亂序等。

因此,現實世界中,事件時間和處理時間的關係如下所示:

圖片 1.png | center | 443x453

從上圖可以看出事件時間和處理時間關係的兩個特點:

  • 處理時滯:也就是處理時間一定比事件事件晚
  • 事件時間偏差:處理時間-事件時間的時間差,並不固定。

因此,處理時間和事件時間,並沒有關係。並且現實場景中,用戶往往都是需要按照事件時間處理數據。然而現在很多流處理系統,爲了簡單,都是按處理時間,將無界數據進行切片,使其變爲一個個小的有界數據片。這樣做就會對真是結果產生誤差。所以,爲了保證最終結果的正確性,流系統一定要具備處理事件時間的能力。

然而要處理事件時間,又會產生其他問題,比如:如何判斷事件時間X上的事件已經全部到齊?在現實世界中,是不可能做到的。因此我認爲,不能再使用將無界數據切分成有界數據的方式來處理無界數據集了。好的流計算系統,就應該能夠處理真實世界中複雜的數據,如果出現新數據,結果應該能夠被自動更新或撤回。

在本文和接下來的一系列文章中,會着重討論這種新型的流系統理論。在展開介紹這個理論之前,咱們先來看看目前數據處理的一般模式。

數據處理模式

接下來,我們瞭解以下目前處理這兩種數據類型的常見的核心模型。

有界數據

如何處理有界數據,大家都很熟悉了,如下圖所示,左邊的數據,經過某種數據處理引擎,變成右邊的結構化數據集。

圖片 1.png | center | 415x209

這個模型能處理的場景非常多,但是模型本身確非常簡單。與之相比,處理無界數據的處理方式,更爲複雜。我們先從典型的批處理系統開始,再到專門爲流計算設計的系統爲止,來逐步揭開流處理系統演進的步驟。

無界數據:批

傳統的批處理引擎,通過切片的方式,將無界數據流,切分成一個個有界數據集,再進行計算。

固定窗口

最常用的切片方式,是將數據切成固定大小的窗口(也叫滾窗),然後對每個窗口中的數據進行處理。這種方式對源頭數據在事件時間上有序的場景是有用的。比如已經被切分成文件的日誌等。

在現實世界中,絕大部分場景還是要處理數據完整性問題,無法保證數據到達流計算系統時,事件時間上保序。因此必須有機制能夠使這些遲到的數據重新計算,才能保證結果的正確性(比如,等到所有事件都到再進行計算,或者,拿到晚到數據時,重新對某個小窗口的數據進行計算)

圖片 1.png | center | 516x190

會話(SESSION)

用會話這種更復雜的窗口策略,用批處理系統處理無界數據,處理過程更復雜。首先了解下什麼是會話窗口(session window)。會話窗口的典型定義是被隔開的一系列連續的活動。比如,某個用戶1分鐘內連續來了多次用戶點擊事件,等了3分鐘,又來了幾個連續的點擊事件,則每次連續的點擊事件,都是一個會話窗口。兩個會話窗口的間隔是3分鐘。
在批處理中,每個窗口的數據,可能分佈在兩個小批中。如下圖紅色區域所示。可以通過增大每批數據條數,來減少被階段的會話窗口,但是會增加延時。當然也可以在分批的時候,把同一會話窗口的數據都分在一批,但這會大大增加系統設計的複雜度。

圖片 1.png | center | 747x221

無論何種方式,用傳統批處理來處理會話窗口的效果都不好。更優雅的方式是用流系統來處理會話窗口。稍後我們會詳細討論。

無界數據:流

流計算系統是轉爲處理無界數據而生的。真實的數據具有以下幾個特點:

  • 高度無序:在事件時間上,高度無序。如果用戶需要按照事件事件順序分析數據,就需要在時間上做某種數據shuffle
  • 事件時間偏差不固定,也就是不能指望說在某段時間內,事件時間X的數據都會到齊。

處理以上特點的數據的方式,分爲4類,接下來我們分別瞭解一下各種處理方式:

時間無關

某些場景中,數據的處理與時間無關。在這種場景中,批系統和流系統都可以處理這種場景,並且在結果上沒有太大差別,接下來看幾個時間無關處理的例子。

過濾(Filter)

一個非常典型的與時間無關的操作就是過濾。比如要過濾某個網站的點擊日誌,把從某個domain來的都過濾掉,那這個操作跟數據的有界/無界/事件時間偏差都沒有關係。

圖片 1.png | center | 485x161

內關聯(Inner Joins)

當兩條流做內關聯時,需要把兩條流的數據都持久化到狀態中。當兩邊的數據join上時,就輸出。當然這種方式要考慮數據buffer大小的問題,一般都會按時間來配數據過期策略。

圖片 1.png | center | 499x152

在Join的時候,也有數據完整性問題,一條流中的數據到了,你怎麼知道另一條流相應的數據是否到了?實際上,沒人能回答這個問題。在實際使用過程中,必須要引入時間的概念。

近似算法

之前有很多人嘗試用近似算法來解決流計算問題,比如近似TopN算法,流式K-means算法等。通過近似算法對無界數據進行計算,性能很好,但是可擴展性差,因爲算法都太複雜了。
這些算法中通常都基於處理時間,對事件進行處理,所以無法應對基於事件時間處理的需求。基於這個原因,其實近似算法是另一種形式的__時間無關型__操作。

圖片 1.png | center | 443x147

窗口

其餘兩種流計算中常用的處理無界數據的方式,都是窗口的變體。簡單來說,窗口是獲得(有界或無界)數據源的概念,窗口將數據源沿着時間邊界,切分成有界的數據塊,然後對各個數據塊進行處理。下圖表示了三種窗口類型:

圖片 1.png | center | 469x218

  • 固定窗口(Fixed Window)又稱爲滾窗(Tumbling Window)
    固定窗口在時間維度上,按照固定長度將無界數據流切片,是一種對齊窗口。
  • 滑動窗口(Sliding Window)又稱爲Hop Window,是固定窗口的推廣。由窗口長度和窗口間隔兩個參數確定。如果窗口長度小於窗口間隔,那麼兩個窗口會重合,如上圖中Sliding Window所示。如果窗口長度等於窗口間隔,那麼就是固定窗口。如果窗口長度小雨窗口間隔,那麼就會是一個比較奇怪的採樣窗口,也就是僅對數據集的某些數據做窗口。
  • 會話窗口(Session):是一種動態窗口。會話窗口由一系列事件序列組成,兩個會話窗口之間由沒有任何事件的一段時間間隔。比如,某個用戶1分鐘內連續來了多次用戶點擊事件,等了3分鐘,又來了幾個連續的點擊事件,則每次連續的點擊事件,都是一個會話窗口。兩個會話窗口的間隔是3分鐘。會話窗口通常通過將一系列臨時相關的事件聚合,來分析用戶行爲。每個會話窗口的大小都是不固定的,窗口間的間隔也是不固定的。是一種非常典型的非對齊窗口。

Window可作用域事件時間和處理時間兩個時間域。由於作用域處理時間更常見,我們先來討論作用於處理時間的窗口。

基於處理時間的窗口

圖片 1.png | center | 747x223

基於處理時間的窗口,會把一段時間內的數據都緩存起來,直到時間結束。比如一個5分鐘的窗口,系統會把這5分鐘內的數據都緩存起來,5分鐘時間到了,就將5分鐘內的所有數據送到下游進行計算。
基於處理時間的窗口有幾個特性:

  • 簡單。使用和理解都非常簡單,也不涉及數據晚到的問題。僅僅是將數據緩存一段時間再發到下游進行處理
  • 能直觀判斷窗口是否結束。沒有所謂數據晚到的問題了。因爲系統能夠根據時間精確判斷窗口是否結束。

    • 如果要推斷出數據源的某些信息,處理時間窗口非常合適。許多監控類的需求都用這種窗口都比較合適。比如要計算一個全球範圍的web服務的每秒的流量,來監控服務是否正常。

但是其他大部分場景中,需要依據事件事件來進行計算,用處理事件就不太合適了。比如要監控手機app的使用情況,但是在某段事件中,手機斷網了,等聯網之後,斷網期間手機的運行數據纔會被收集到。此時採集到數據的事件時間和處理時間是有很大偏差的。

現實情況中,很多類似以上情況的場景,都需要基於事件時間來處理。

基於事件時間的窗口

基於事件時間的窗口是最標準的窗口。下圖展示了一個基於事件時間的1小時固定窗口的例子,黑色箭頭的兩個數據是兩個遲到數據:

圖片 1.png | center | 747x277

要特別注意箭頭中所示的兩個數據,兩個數據根據處理時間所在的窗口,跟事件時間發生的窗口不是同一個。因此如果基於處理時間的話,結果就是錯的。只有基於事件時間進行計算,才能保證數據的正確性。

另一個基於事件時間窗口的好處是可以創建動態大小的窗口,比如會話窗口,避免出現上文__無界數據:批__章節例子中所提到的現象:一個session窗口的數據,由於窗口大小固定,被切分到不同窗口中,對下游計算造成障礙。

圖片 1.png | center | 747x277

上圖展示了基於事件時間的會話窗口。基於事件發生的時間,數據被分到各個會話窗口中。黑色箭頭表明了數據晚到,因此需要做數據shuffle將其放入正確的窗口中。

當然,天下沒有免費的午餐。事件時間窗口功能很強大,但由於遲到數據的原因,窗口的存在時間比窗口本身的大小要長很多,導致的兩個明顯的問題是:

  • 緩存:事件時間窗口需要存儲更長時間內的數據。慶幸的是,現在存儲越來越便宜了。經過良好設計的系統,會有一層內存做緩存,其他的數據都持久化存儲在更便宜的存儲上。並且,很多聚合操作,如SUM/AVG等,可以做增量計算,並不需要保存所有數據。
  • 完整性:基於事件時間的窗口,我們也不能判斷什麼時候窗口的數據都到齊了。很多系統,如MillWheel,Flink通過watermark,能夠推斷一個相對精確的窗口結束時間。但是這種方式並不能得到完全正確的結果。因此,解決這個問題的更好的方式,應該是讓用戶能定義何時輸出窗口結果,並且定義當遲到數據到來時,如何更新之前窗口計算的結果。

總結

本文主要討論了幾個問題:

  • 澄清了一些術語的定義,專注於‘流’的定義,而不是已有流計算系統的實現
  • 研究了目前批/流系統的能力,強調,在功能上,流是批的超集。
  • 提出瞭如果流系統在功能上要超越批系統,需要具備的兩個能力,分別是:正確性和在各時間域處理數據的能力。
  • 強調了事件時間和處理時間的巨大區別。提出了基於這兩個時間處理數據的難點。
  • 調查了主流數據處理系統處理有界和無界數據的方式。將無界數據處理分爲四類:時間無關,近似估計,基於處理時間的窗口和基於事件時間的窗口
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章