1. 程式人生 > >流式處理框架對比

流式處理框架對比

流式處理 處理 ont 調優 cnblogs eve 上線 用戶 避免

分布式流處理是對無邊界數據集進行連續不斷的處理、聚合和分析的過程,與MapReduce一樣是一種通用計算框架,期望延遲在毫秒或者秒級別。這類系統一般采用有向無環圖(DAG)。DAG是任務鏈的圖形化表示,用它來描述流處理作業的拓撲。在選擇不同的流處理系統時,通常會關註以下幾點:

  • 運行時和編程模型:平臺框架提供的編程模型決定了許多特色功能,編程模型要足夠處理各種應用場景。
  • 函數式原語:流處理平臺應該能提供豐富的功能函數,比如,map或者filter這類易擴展、處理單條信息的函數;處理多條信息的函數aggregation;跨數據流、不易擴展的操作join等。
  • 狀態管理:大部分應用都需要保持狀態處理的邏輯。流處理平臺應該提供存儲、訪問和更新狀態信息。
  • 消息傳輸保障:消息傳輸保障一般有三種:at most once,at least once和exactly once。容錯:流處理框架中的失敗會發生在各個層次,比如,網絡部分,磁盤崩潰或者節點宕機等。流處理框架應該具備從所有這種失敗中恢復,並從上一個成功的狀態(無臟數據)重新消費。
    1. At most once:消息傳輸機制是每條消息傳輸零次或者一次,即消息可能會丟失;
    2. A t least once:意味著每條消息會進行多次傳輸嘗試,至少一次成功,即消息傳輸可能重復但不會丟失;
    3. Exactly once:消息傳輸機制是每條消息有且只有一次,即消息傳輸既不會丟失也不會重復。
  • 性能:延遲時間(Latency),吞吐量(Throughput)和擴展性(Scalability)是流處理應用中極其重要的指標。
  • 平臺的成熟度和接受度:成熟的流處理框架可以提供潛在的支持,可用的庫,甚至開發問答幫助。選擇正確的平臺會在這方面提供很大的幫助。

運行時和編程模型


運行時和編程模型是一個系統最重要的特質,因為它們定義了表達方式、可能的操作和將來的局限性。因此,運行時和編程模型決定了系統的能力和適用場景。實現流處理系統有兩種完全不同的方式:

  1. 原生流處理:指所有輸入的記錄一旦到達即會一個接著一個進行處理。示例如下:微批處理:把輸入的數據按照某種預先定義的時間間隔(典型的是幾秒鐘)分成短小的批量數據,流經流處理系統。示例如下:
    • 技術分享
    • 技術分享

兩種方法都有其先天的優勢和不足,原生流處理的優勢在於它的表達方式。數據一旦到達立即處理,這些系統的延遲性遠比其它微批處理要好。除了延遲性外,原生流處理的狀態操作也容易實現。一般原生流處理系統為了達到低延遲和容錯性會花費比較大的成本,因為它需要考慮每條記錄。原生流處理的負載均衡也是個問題。比如,我們處理的數據按key分區,如果分區的某個key是資源密集型,那這個分區很容易成為作業的瓶頸。

微批處理。將流式計算分解成一系列短小的批處理作業,也不可避免的減弱系統的表達力。像狀態管理或者join等操作的實現會變的困難,因為微批處理系統必須操作整個批量數據。並且,batch interval會連接兩個不易連接的事情:基礎屬性和業務邏輯。相反地,微批處理系統的容錯性和負載均衡實現起來非常簡單,因為微批處理系統僅發送每批數據到一個worker節點上,如果一些數據出錯那就使用其它副本。微批處理系統很容易建立在原生流處理系統之上。

編程模型一般分為組合式和聲明式。組合式編程提供基本的構建模塊,它們必須緊密結合來創建拓撲。新的組件經常以接口的方式完成。相對應地,聲明式API操作是定義的高階函數。它允許我們用抽象類型和方法來寫函數代碼,並且系統創建拓撲和優化拓撲。聲明式API經常也提供更多高級的操作(比如,窗口函數或者狀態管理)。

主流開源流處理系統


主源開源的流處理系統如下圖,暫時不介紹商業的系統,比如Google MillWheel或者Amazon Kinesis,也不會涉及很少使用的Intel GearPump或者Apache Apex

技術分享

Apache Storm最開始是由Nathan Marz和他的團隊於2010年在數據分析公司BackType開發的,後來BackType公司被Twitter收購,接著Twitter開源Storm並在2014年成為Apache頂級項目。毋庸置疑,Storm成為大規模流數據處理的先鋒,並逐漸成為工業標準。Storm是原生的流處理系統,提供low-level的API。Storm使用Thrift來定義topology和支持多語言協議,使得我們可以使用大部分編程語言開發,Scala自然包括在內

Trident是對Storm的一個更高層次的抽象,Trident最大的特點以batch的形式進行流處理。Trident簡化topology構建過程,增加了窗口操作、聚合操作或者狀態管理等高級操作,這些在Storm中並不支持。相對應於Storm的At most once流傳輸機制,Trident提供了Exactly once傳輸機制。Trident支持Java,Clojure和Scala

當前Spark是非常受歡迎的批處理框架,包含Spark SQL,MLlib和Spark Streaming。Spark的運行時是建立在批處理之上,因此後續加入的Spark Streaming也依賴於批處理,實現了微批處理。接收器把輸入數據流分成短小批處理,並以類似Spark作業的方式處理微批處理。Spark Streaming提供高級聲明式API(支持Scala,Java和Python)

Samza最開始是專為LinkedIn公司開發的流處理解決方案,並和LinkedIn的Kafka一起貢獻給社區,現已成為基礎設施的關鍵部分。Samza的構建嚴重依賴於基於log的Kafka,兩者緊密耦合。Samza提供組合式API,當然也支持Scala

Flink是個相當早的項目,開始於2008年,但只在最近才得到註意。Flink是原生的流處理系統,提供high level的API。Flink也提供API來像Spark一樣進行批處理,但兩者處理的基礎是完全不同的。Flink把批處理當作流處理中的一種特殊情況。在Flink中,所有的數據都看作流,是一種很好的抽象,因為這更接近於現實世界

快速的介紹流處理系統之後,讓我們以下面的表格來更好清晰的展示它們之間的不同:

技術分享

容錯性


流處理系統的容錯性與生俱來的比批處理系統難實現。當批處理系統中出現錯誤時,我們只需要把失敗的部分簡單重啟即可;但對於流處理系統,出現錯誤就很難恢復。因為線上許多作業都是7 x 24小時運行,不斷有輸入的數據。流處理系統面臨的另外一個挑戰是狀態一致性,因為重啟後會出現重復數據,並且不是所有的狀態操作是冪等的。

以是流處理框架容錯性處理方案:

Apache Storm:Storm使用上遊數據備份和消息確認的機制來保障消息在失敗之後會重新處理。消息確認原理:每個操作都會把前一次的操作處理消息的確認信息返回。Topology的數據源備份它生成的所有數據記錄。當所有數據記錄的處理確認信息收到,備份即會被安全拆除。失敗後,如果不是所有的消息處理確認信息收到,那數據記錄會被數據源數據替換。這保障了沒有數據丟失,但數據結果會有重復,這就是at-least once傳輸機制。

Storm采用取巧的辦法完成了容錯性,對每個源數據記錄僅僅要求幾個字節存儲空間來跟蹤確認消息。純數據記錄消息確認架構,盡管性能不錯,但不能保證exactly once消息傳輸機制,所有應用開發者需要處理重復數據。Storm存在低吞吐量和流控問題,因為消息確認機制在反壓下經常誤認為失敗。

Spark Streaming:Spark Streaming實現微批處理,容錯機制的實現跟Storm不一樣的方法。微批處理的想法相當簡單。Spark在集群各worker節點上處理micro-batches。每個micro-batches一旦失敗,重新計算就行。因為micro-batches本身的不可變性,並且每個micro-batches也會持久化,所以exactly once傳輸機制很容易實現。

Samza:Samza的實現方法跟前面兩種流處理框架完全不一樣。Samza利用消息系統Kafka的持久化和偏移量。Samza監控任務的偏移量,當任務處理完消息,相應的偏移量被移除。消息的偏移量會被checkpoint到持久化存儲中,並在失敗時恢復。但是問題在於:從上次checkpoint中修復偏移量時並不知道上遊消息已經被處理過,這就會造成重復。這就是at least once傳輸機制。

Apache Flink:Flink的容錯機制是基於分布式快照實現的,這些快照會保存流處理作業的狀態(本文對Flink的檢查點和快照不進行區分,因為兩者實際是同一個事物的兩種不同叫法。Flink構建這些快照的機制可以被描述成分布式數據流的輕量級異步快照,它采用Chandy-Lamport算法實現。)。如果發生失敗的情況,系統可以從這些檢查點進行恢復。Flink發送checkpoint的柵欄(barrier)到數據流中(柵欄是Flink的分布式快照機制中一個核心的元素),當checkpoint的柵欄到達其中一個operator,operator會接所有收輸入流中對應的柵欄(比如,圖中checkpoint n對應柵欄n到n-1的所有輸入流,其僅僅是整個輸入流的一部分)。所以相對於Storm,Flink的容錯機制更高效,因為Flink的操作是對小批量數據而不是每條數據記錄。但也不要讓自己糊塗了,Flink仍然是原生流處理框架,它與Spark Streaming在概念上就完全不同。Flink也提供exactly once消息傳輸機制。

狀態管理


狀態管理大部分大型流處理應用都涉及到狀態。相對於無狀態的操作(其只有一個輸入數據,處理過程和輸出結果),有狀態的應用會有一個輸入數據和一個狀態信息,然後處理過程,接著輸出結果和修改狀態信息。因此,我們不得不管理狀態信息,並持久化。我們期望一旦因某種原因失敗,狀態能夠修復。狀態修復有可能會出現小問題,它並不總是保證exactly once,有時也會出現消費多次,但這並不是我們想要的。

據我們所知,Storm提供at-least once的消息傳輸保障。那我們又該如何使用Trident做到exactly once的語義。概念上貌似挺簡單,你只需要提交每條數據記錄,但這顯然不是那麽高效。所以你會想到小批量的數據記錄一起提交會優化。Trident定義了幾個抽象來達到exactly once的語義,見下圖,其中也會有些局限。

Spark Streaming是微批處理系統,它把狀態信息也看做是一種微批量數據流。在處理每個微批量數據時,Spark加載當前的狀態信息,接著通過函數操作獲得處理後的微批量數據結果並修改加載過的狀態信息。

技術分享

Samza實現狀態管理是通過Kafka來處理的。Samza有真實的狀態操作,所以其任務會持有一個狀態信息,並把狀態改變的日誌推送到Kafka。如果需要狀態重建,可以很容易的從Kafka的topic重建。為了達到更快的狀態管理,Samza也支持把狀態信息放入本地key-value存儲中,所以狀態信息不必一直在Kafka中管理,見下圖。不幸的是,Samza只提供at-least once語義,exactly once的支持也在計劃中

技術分享

Flink提供狀態操作,和Samza類似。Flink提供兩種類型的狀態:一種是用戶自定義狀態;另外一種是窗口狀態。如圖,第一個狀態是自定義狀態,它和其它的的狀態不相互作用。這些狀態可以分區或者使用嵌入式Key-Value存儲狀態[文檔一和二]。當然Flink提供exactly-once語義。下圖展示Flink長期運行的三個狀態。

技術分享

小結


對於延遲性來說,微批處理一般在秒級別,大部分原生流處理在百毫秒以下,調優的情況下Storm可以很輕松的達到十毫秒。同時也要記住,消息傳輸機制保障,容錯性和狀態恢復都會占用機器資源。例如,打開容錯恢復可能會降低10%到15%的性能,Storm可能降低70%的吞吐量。

總之,天下沒有免費的午餐。對於有狀態管理,Flink會降低25%的性能,Spark Streaming降低50%的性能。也要記住,各大流處理框架的所有操作都是分布式的,通過網絡發送數據是相當耗時的,所以盡量利用數據本地性,也盡量優化你的應用的序列化。

項目成熟度:Storm是第一個主流的流處理框架,後期已經成為長期的工業級的標準,並在像Twitter,Yahoo,Spotify等大公司使用。Spark Streaming是最近最流行的Scala代碼實現的流處理框架。現在Spark Streaming被公司(Netflix, Cisco, DataStax, Intel, IBM等)日漸接受。Samza主要在LinkedIn公司使用。Flink是一個新興的項目,很有前景。你可能對項目的貢獻者數量也感興趣。Storm和Trident大概有180個代碼貢獻者;整個Spark有720多個;根據github顯示,Samza有40個;Flink有超過130個代碼貢獻者。

High level API:具有high level API的流處理框架會更簡潔和高效;

Storm:Storm非常適合任務量小但速度要求高的應用。如果你主要在意流處理框架的延遲性,Storm將可能是你的首先。但同時也要記住,Storm的容錯恢復或者Trident的狀態管理都會降低整體的性能水平。也有一個潛在的Storm更新項目-Twitter的Heron,Heron設計的初衷是為了替代Storm,並在每個單任務上做了優化但同時保留了API。

Spark Streaming:如果你得基礎架構中已經設計到Spark,那Spark Streaming無疑是值得你嘗試的。因為你可以很好的利用Spark各種library。如果你需要使用Lambda架構,Spark Streaming也是一個不錯的選擇。但你要時刻記住微批處理的局限性,以及它的延遲性問題。

Samza:如果你想使用Samza,那Kafka應該是你基礎架構中的基石,好在現在Kafka已經成為家喻戶曉的組件。像前面提到的,Samza一般會搭配強大的本地存儲一起,這對管理大數據量的狀態非常有益。它可以輕松處理上萬千兆字節的狀態信息,但要記住Samza只支持at least once語義。

Flink:Flink流處理系統的概念非常不錯,並且滿足絕大多數流處理場景,也經常提供前沿的功能函數,比如,高級窗口函數或者時間處理功能,這些在其它流處理框架中是沒有的。同時Flink也有API提供給通用的批處理場景。但你需要足夠的勇氣去上線一個新興的項目,並且你也不能忘了看下Flink的roadmap。

本文參考地址:http://www.36dsj.com/archives/71734

流式處理框架對比