標籤:
原文:http://highlyscalable.wordpress.com/2013/08/20/in-stream-big-data-processing/
Ilya Katsov
相當長一段時間以來。大資料社區已經普遍認識到了批量資料處理的不足。
非常多應用都對即時查詢和串流產生了迫切需求。近期幾年,在這個理念的推動下。催生出了一系列解決方式。Twitter Storm,Yahoo S4,Cloudera Impala,Apache Spark和Apache Tez紛紛增加大資料和NoSQL陣營。本文嘗試探討串流系統用到的技術,分析它們與大規模批量處理和OLTP/OLAP資料庫的關係。並探索一個統一的查詢引擎怎樣才幹同一時候支援流式、批量和OLAP處理。
在Grid Dynamics,我們面臨的需求是構建一個流式資料處理系統。每天須要處理80億事件,並提供容錯能力和嚴格事務性,即不能丟失或反覆處理事件。
新系統是現有系統的補充和繼任者。現有系統基於Hadoop,資料處理延遲高,並且維護成本太高。
此類需求和系統相當通用和典型。所以我們在下文將其描寫敘述為規範模型,作為一個抽象問題陳述。
從高層次展示了我們的生產環境概況:
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaWRvbnR3YW50b2Jl/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" >
這是一套典型的大資料基礎設施:多個資料中心的各個應用程式都在生產資料,資料通過資料收集子系統輸送到位於中心設施的HDFS上,然後未經處理資料通過標準的Hadoop工具棧(MapReduce,Pig,Hive)進行匯總和分析,匯總結果儲存在HDFS和NoSQL上,再匯出到OLAP資料庫上被定製的使用者應用訪問。我們的目標是給全部的設施配備上新的串流引擎(見圖底部)。來處理大部分密集資料流。輸送預匯總的資料到HDFS,降低Hadoop中未經處理資料量和批量job的負載。
串流引擎的設計由下面需求驅動:
為了弄明確怎樣實現這樣一個系統,我們討論下面主題:
The article isbased on a research project developed at Grid Dynamics Labs. Much of the creditgoes to Alexey Kharlamov and Rafael Bagmanov who led the project and othercontributors: Dmitry Suslov, Konstantine Golikov, Evelina Stepanova, AnatolyVinogradov, Roman Belous, and Varvara Strizhkova.
分散式查詢處理基礎
分布式流式資料處理顯然和Distributed Relational Database Service有聯絡。很多標準查詢處理技術都能應用到串流引擎上來,所以理解分散式查詢處理的經典演算法,理解它們和串流以及其它流行架構比方MapReduce的關係,是很實用的。
分散式查詢處理已經發展了數十年,是一個非常大的知識領域。我們從一些主要技術的簡明概述入手,為下文的討論提供基礎。
分區和Shuffling
分布式和並行查詢處理重度依賴資料分區,將大資料打散分成多片讓各個獨立進程分別進行處理。
查詢處理可能包含多步。每一步都有自己的分區策略。所以資料shuffling操作廣泛應用於分散式資料庫中。
雖然用於選擇和投射操作的最優分區須要一定技巧(比方在範圍查詢中),但我們能夠如果在流式資料過濾中,使用雜湊分割在各處理器中分發資料足以行得通。
分布式join不是那麼簡單,須要深入研究。在分布式環境中。並行join通過資料分區實現,也就是說,資料分布在各個處理器中,每一個處理器執行串列join演算法(比方嵌套迴圈join或者排序-合并join或者雜湊join)處理部分資料。終於結果從不同處理器擷取合并得來。
分布式join主要採用兩種資料分區技術:
不相交資料分區技術使用join key將資料shuffle到不同分區,分區資料互不重疊。
每一個處理器在自己分區資料上運行join操作,不同處理器的結果簡單拼接產生終於結果。考慮R和S資料集join的範例。它們以數值鍵k進行join,以簡單的模數函數進行分區。
(如果資料基於某種策略。已經分布在各個處理器上):
示範了劃分-廣播join演算法。資料集R被劃分成多個不相交的分區(圖中的R1,R2和R3)。資料集S被拷貝到全部的處理器上。在分散式資料庫中。劃分操作本身通常不包括在查詢過程中,由於資料初始化已經分布在不同節點中。
這樣的策略適用於大資料集join小資料集,或者兩個小資料集之間join。流式資料處理系統能應用這樣的技術,比方將待用資料(admixture)和資料流進行join。
Group By處理過程也依賴shuffling。本質上和MapReduce是類似的。考慮下面情境,資料集依據字元欄位分組,再對每組的數值欄位求和:
在這個範例中。計算過程包括兩步:本地匯總和全域匯總。這基本和Map/Reduce操作相應。本地匯總是可選的。未經處理資料能夠在全域匯總階段傳輸、shuffle、匯總。
本節的總體觀點是。上面的演算法都天然能通過訊息傳遞架構模式實現。也就是說,查詢運行引擎能夠看做是由訊息佇列串連起來的分布式網路節點群組成。概念上和串流管道是類似的。
管道
前一節中。我們注意到非常多分散式查詢處理演算法都類似訊息傳遞網路。
可是。這不足以說明串流的高效性:查詢中的全部操作應該形成鏈路,資料流平滑通過整個管道,也就是說。不論什麼操作都不能堵塞處理過程,不能等待一大塊輸入而不產生不論什麼輸出。也不用將中間結果寫入硬碟。
有一些操作比方排序,天然不相容這樣的理念(顯而易見,排序在處理完輸入之前都不能產生不論什麼輸出),但管道演算法適用於非常多情境。一個典型的管道例如以所看到的:
在這個範例中,使用三個處理器雜湊join四個資料集:R1,S1。S2和S3。首先並行給S1,S2和S3建立雜湊表,然後R1元組逐個流過管道,從S1。S2和S3雜湊表中尋找相匹配記錄。串流天然能使用該技術實現資料流和待用資料的join。
在關係型資料庫中,join操作還會使用對稱雜湊join演算法或其它進階變種。
對稱雜湊join是雜湊join演算法的泛化形式。正常的雜湊join至少須要一個輸入全然可用才幹輸出結果(當中一個輸入用來建立雜湊表),而對稱雜湊join為兩個輸入都維護雜湊表,當資料元組抵達後。分別填充:
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaWRvbnR3YW50b2Jl/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" >
元組抵達時,先從另外一個資料流相應的雜湊表尋找。假設找到匹配記錄,則輸出結果。然後元組被插入到自身資料流相應的雜湊表。
當然。這樣的演算法對無限流進行全然join不是太有意義。非常多情境下。join都作用於有限的時間表單或者其它類型的緩衝區上。比方用LFU快取資料流中最經常使用的元組。
對稱雜湊join適用於緩衝區大過流的速率,或者緩衝區被應用邏輯頻繁清除,或者緩衝回收策略不可預見的情境。在其它情況下。使用簡單雜湊join已足夠。由於緩衝區始終是滿的,也不會堵塞處理流程:
值得注意的是。串流往往須要採用複雜的流關聯演算法,記錄匹配不再是基於欄位相等條件,而是基於評分度量,在這樣的情境下。須要為兩個流維護更為複雜的緩衝體系。
串流模式
前一節中,我們討論了一些在大規模並行流處理中用到的標準查詢技術。
從概念層面上來看,似乎一個高效分散式資料庫查詢引擎能勝任串流,反之亦然,一個串流系統也應該能充當分散式資料庫查詢引擎的角色。Shuffling和管道是分散式查詢處理的關鍵技術,並且通過訊息傳遞網路可以自然而然地實現它們。
然而真實情況沒那麼簡單。
在資料庫查詢引擎中。可靠性不是那麼關鍵,由於一個僅僅讀查詢總是可以被又一次執行,而流式系統則必須重點關注訊息的可靠處理。在本節中,我們討論流式系統保證訊息傳遞的技術。和其它一些在標準查詢處理中不那麼典型的模式。
流回放
在串流系統中,時光倒流和回放資料流的能力至關重要。由於下面原因:
- 這是確保資料正確處理的唯一方式。即使資料處理管道是容錯的,也難以確保資料處理邏輯是無缺陷的。人們總是面臨修複和又一次部署系統的需求,須要在新版本號碼的管道上回放資料。
- 問題調查須要即席查詢。假設發生了問題,人們可能須要增加日誌或者改動代碼,在產生問題的資料上重跑系統。
- 即使錯誤不常發生。即使系統整體上是容錯的,串流系統也必須設計成在錯誤發生時可以從資料來源中又一次讀取特定訊息。
因此,輸入資料通常通過緩衝區從資料來源流入流式管道,同意client在緩衝區中前後移動讀取指標。
Kafka訊息佇列系統就實現了這樣一個緩衝區,支援可擴充分布式部署和容錯,同一時候提供高效能。
流回放要求系統設計至少考慮下面需求:
- 系統可以儲存提前定義周期內的未經處理資料。
- 系統可以撤銷一部分處理結果。回放相應的輸入資料。產出新版本號碼結果。
- 系統可以高速倒回,回放資料。然後追上源源不斷的資料流進度。
血緣跟蹤
在流式系統中,事件流過一連串的處理器直到終點(比方外部資料庫)。每一個輸入事件產生一個由子事件節點(血緣)構成的有向圖,有向圖以終於結果為終點。
為了保障資料處理可靠性,整個圖都必須被成功處理,並且在失敗的情況下能重新啟動處理過程。
實現高效血緣跟蹤是一個難題。我們先介紹Twitter Storm是怎樣跟蹤訊息,保障“至少一次”訊息處理語義:
以上實現非常優雅,具有去中心化特性:每一個節點獨立發送確認訊息。不須要一個中心節點來顯式跟蹤血緣。
然而。對於維護了滑動表單或其它類型緩衝區的資料流,實現交易處理變得比較困難。比方,滑動表單內可能包括成千上萬個事件。非常多事件處於未提交或計算中狀態,須要頻繁持久化,管理事件確認過程難度非常大。
Apache Spark[3]使用的是第二種實現方法,其想法是把終於結果看作是輸入資料的處理函數。為了簡化血緣跟蹤,架構分批處理事件,結果也是分批的,每一批都是輸入批次的處理函數。
結果能夠分批並行計算,假設某個計算失敗,架構僅僅要重跑它即可。考慮下面範例:
在這個範例中,架構在滑動表單上join兩個流。然後結果再經過一個處理階段。架構把流拆分成批次,每一個批次指定ID,架構隨時都能依據ID擷取對應批次。
串流被拆分為一系列事務,每一個交易處理一組輸入批次,使用處理函數轉換資料,並儲存結果。在中,紅色加亮部分代表了一次事務。假設事務失敗,架構重跑它,最重要的是,事務是能夠並行的。
這樣的方式簡潔而強大,實現了集中式交易管理,並天然提供“僅僅運行一次”訊息處理語義。
這樣的技術還同一時候適用於批量處理和串流,由於無論輸入資料是否是流式的,都把它們拆分成一系列批次。
狀態檢查點
前一節,我們在血緣跟蹤演算法中使用簽名(校正和)提供了“至少一次”訊息傳遞語義。
該技術改善了系統的可靠性,但留下了至少兩個開放式問題:
Twitter Storm使用下面協議解決這些問題:
假設資料來源是容錯的,可以被回放,那麼事務能保障“僅僅運行一次”處理語義。可是,即使使用大容量分批處理,持久化狀態更新也會導致嚴重的效能退化。
所以。應該儘可能降低或者避免中間計算結果狀態。
補充說明的是,狀態寫入也能通過不同方式實現。最直接的方式是在事務提交過程中,把記憶體中狀態拷貝到持久化儲存。
這樣的方式不適用於大規模狀態(比方滑動表單等)。還有一種可選方式是儲存某種交易記錄,比方將原始狀態轉化為新狀態的一系列動作記錄(對滑動表單來說,可以是一組加入和清理事件)。儘管這樣的方式須要從日誌中重建狀態,災難恢複變得更麻煩,但在非常多情境下。它都能提供更好的效能。
可加性和草圖
中間和終於計算結果的可加性非常重要,能極大地簡化流式資料處理系統的設計,實現,維護和恢複。可加性意味著大範圍時間或者大容量資料分區的計算結果可以由更小的時間範圍或者更小的分區結果組合而來。比方,每日PV量等於每小時PV量之和。
狀態可加性同意將資料流切分處理,如我們在前一節討論,每一個批次都可以被獨立計算/重算,這有助於簡化血緣跟蹤和降低狀態維護的複雜性。
實現可加性往往不輕鬆:
草圖(Sketches)是將不可加值轉換為可加值的有效方法。在上面的範例中,ID列表能夠被緊湊的可加性統計計數器取代。計數器提供近似值而不是精確值,但在非常多應用中都是能夠接受的。草圖在互連網廣告等特定領域非常流行,能夠被看做一種獨立的串流模式。草圖技術的深入綜述請見[5]。
邏輯時間跟蹤
流式計算中一般會依賴時間:匯總和Join一般作用在滑動時間表單上;處理邏輯往往依賴事件的時間間隔等。顯然,串流系統應該有自己的時間視圖,而不應該使用CPU掛鐘時間。由於發生問題時,資料流和特定事件會被回放。所以實現正確的時間跟蹤並不簡單。
通常。全域的邏輯時間概念能夠通過下面方式實現:
- 原始系統產生的全部事件都應該標記上時間戳記。
- 管道中的處理器處理流時,跟蹤最大時間戳記,假設持久化的全域時鐘落後了,就把它更新為最大時間戳記。其它處理器與全域時鐘進行時間同步
- 在資料回放時。重設全域時鐘。
持久化儲存匯總
我們已經討論了持久化儲存能夠用於狀態檢查點,但這不是流式系統引入外部儲存的唯一作用。考慮使用Cassandra在時間表單上join多個資料流的情境。
不用再維護記憶體中的事件緩衝區,我們能夠把全部資料流的傳入事件儲存到Casandra中,使用join key作為row key,所看到的:
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaWRvbnR3YW50b2Jl/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" >
在還有一邊,第二個處理器定期遍曆資料記錄。組裝和發送join後的記錄,清理超出時間表單的事件。
Cassandra還能夠依據時間戳記排序事件來加速處理過程。
不對的實現會讓整個流式資料處理過程功虧一簣——即使使用Cassandra或者Redis等高速儲存系統,單獨寫入每條資料也會引入嚴重的效能瓶頸。
還有一方面,使用儲存系統提供了更完好的狀態持久化功能。假設應用批量寫入等最佳化手段,在非常多情境下,也能達成可接受的效能目標。
滑動表單彙總
流式資料處理常常處理 “過去10分鐘流的某個資料值求和是多少” 等類似查詢,即時間表單上的連續查詢。針對這類查詢,最直接的解決方式是分別計算各個時間表單的sum等彙總函式。非常顯然,這樣的方案不是最優的。由於兩個連續的時間表單執行個體具有高度相似性。
假設時刻T的表單包括樣本{s(0),s(1),s(2),...,s(T-1),s(T)},那麼時刻T+1的表單就包括{s(1),s(2),s(3)...,s(T),s(T+1)}。觀察可知能夠使用增量處理。
時間表單之上的增量計算也被廣泛應用在數字訊號處理中。包含軟體和硬體。典型範例是計算sum值。
假設目前時間表單的sum值已知,那麼下次時間表單的sum值就能通過加上新的樣本和減去表單中最老的樣本得出。
類似技術不僅能用於求和和乘積等簡單彙總函式,也能用於更複雜的轉換過程。比方。SDFT(滑動離散傅裡葉變換)演算法[4]就比對每一個表單使用FFT(高速傅裡葉變換)演算法要高效得多。
查詢處理管道:Storm, Cassandra, Kafka
如今回到文章一開始提出的實際問題上來。我們基於Storm,Kafka和Cassandra(這些組件應用了前文介紹的技術)設計和實現了自己的串流系統。在此。我們僅提供解決方式的簡明概述——具體描寫敘述全部實現上的坑和技巧的篇幅太長,可能須要單獨一篇文章。
系統理所當然使用Kafka0.8。
Kafka作為分區、容錯的事件緩衝區,能夠實現流回放,能夠輕鬆加入新的事件生產者和消費者。增強了系統的擴充性。Kafka讀指標回溯的能力也使隨機訪問傳入的資料批次成為可能,對應地。能夠實現Spark風格的血緣跟蹤。也能夠將系統輸入指向HDFS處理曆史資料。
如之前描寫敘述。Cassandra用於實現狀態檢查點和持久化儲存彙總。在非常多使用情境中。Cassandra也用於儲存終於結果。
TwitterStorm是系統的基石。
全部的活動查詢處理都執行於Storm的topologies中,topologies和Kafka、Cassandra進行互動。
一些資料流是簡單的:資料抵達Kafka;Storm讀取並處理。然後把結果儲存在Cassandra或者其它地方。其它資料流更為複雜:一個Storm topology通過Kafka或Cassandra將資料傳遞給還有一個topology。展示了兩個此類型資料流(紅色和藍色曲線箭頭)。
邁向統一大資料處理平台
現有的Hive,Storm和Impala等技術讓我們處理大資料時遊刃有餘,複雜分析和機器學習時使用批量處理。線上分析時使用即時查詢處理,連續查詢時使用串流。更進一步。Lambda架構還能有效整合這些解決方式。這給我們帶來的問題是:將來這些技術和方法如何才幹聚整合一個統一解決方式。本節我們討論分布式關係查詢處理,批量處理和串流最突出的共同點。合計出可以覆蓋全部使用者情境,從而在這個領域最具發展潛力的解決方式。
關鍵之處在於,關係型查詢處理,MapReduce和串流都能通過shuffling和管道等同樣的概念和技術來實現。同一時候:
以上兩點暗示,可調的持久化策略(基於記憶體的訊息傳遞或者儲存在硬碟上)和可靠性是我們想象中統一查詢引擎的顯著特性。
統一查詢引擎為高層的架構提供一組處理原語和介面。
在新興技術中,下面兩者值得重點關註:
- Apache Tez[8],Stinger Initiative[9]的一部分。Apache Tez通過引入一組細粒度的查詢處理原語來替代MapReduce架構。它的目標是讓Apache Pig和Apache Hive等架構把查詢語句和指令碼分解成高效的查詢處理管道,而不是一系列的MapReduce Job,後者通常非常慢。由於須要儲存中間結果。
- Apache Spark[10].Spark項目可能是最先進和最有前途的統一大資料處理平台,它已經包括了批量處理架構。SQL查詢引擎和串流架構。
References
- Wilschut and P. Apers,“Dataflow Query Execution in a Parallel Main-Memory Environment “
- T. Urhan and M. Franklin,“XJoin: A Reactively-Scheduled Pipelined Join Operator“
- M. Zaharia, T. Das, H. Li, S.Shenker, and I. Stoica, “Discretized Streams: An Ef?cient and Fault-TolerantModel for Stream Processing on Large Clusters”
- E. Jacobsen and R. Lyons, “The Sliding DFT“
- Elmagarmid, Data Streams Modelsand Algorithms
- N. Marz, “Big Data Lambda Architecture”
u=D6CKvfYGoZxERFXGxs9UBEREu7W0HYs0r2ltZ5sv7GeJ13itwfjRuHELCugrUlhgffAMPEIWsYv%2FvWpsxg0lL4tlhy8n4VVx%2FHWfCEebudaVIQEh5yspl2kee4hyCg%3D%3D&b=6">J. Kinley, “The Lambda architecture: principles for architecting realtimeBig Data systems”
u=D6CKv%2FgZsIBBWlTYyMVUE15E9rGnV4c0smlpbZJ0&b=6">http://hortonworks.com/hadoop/tez/
- http://hortonworks.com/stinger/
u=D6CKpOcKtoQCXUnFydMZBB9Gq77p&b=6">http://spark-project.org/
翻譯-In-Stream Big Data Processing 流式大資料處理