Storm,Trident,Spark Streaming,Samza和Flink主流流處理框架比較
文 | Petr Zapletal ,譯者 | 俠天
分布式流處理是對無邊界數據集進行連續不斷的處理、聚合和分析。它跟MapReduce一樣是一種通用計算,但我們期望延遲在毫秒或者秒級別。這類系統一般采用有向無環圖(DAG)。
DAG是任務鏈的圖形化表示,我們用它來描述流處理作業的拓撲。如下圖,數據從sources流經處理任務鏈到sinks。單機可以運行DAG,但本篇文章主要聚焦在多臺機器上運行DAG的情況。
關注點
當選擇不同的流處理系統時,有以下幾點需要注意的:
- 運行時和編程模型:平臺框架提供的編程模型決定了許多特色功能,編程模型要足夠處理各種應用場景。這是一個相當重要的點,后續會繼續。
- 函數式原語:流處理平臺應該能提供豐富的功能函數,比如,map或者filter這類易擴展、處理單條信息的函數;處理多條信息的函數aggregation;跨數據流、不易擴展的操作join。
- 狀態管理:大部分應用都需要保持狀態處理的邏輯。流處理平臺應該提供存儲、訪問和更新狀態信息。
- 消息傳輸保障:消息傳輸保障一般有三種:at most once,at least once和exactly once。At most once的消息傳輸機制是每條消息傳輸零次或者一次,即消息可能會丟失;A t least once意味著每條消息會進行多次傳輸嘗試,至少一次成功,即消息傳輸可能重復但不會丟失;Exactly once的消息傳輸機制是每條消息有且只有一次,即消息傳輸既不會丟失也不會重復。
- 容錯:流處理框架中的失敗會發生在各個層次,比如,網絡部分,磁盤崩潰或者節點宕機等。流處理框架應該具備從所有這種失敗中恢復,并從上一個成功的狀態(無臟數據)重新消費。
- 性能:延遲時間(Latency),吞吐量(Throughput)和擴展性(Scalability)是流處理應用中極其重要的指標。
- 平臺的成熟度和接受度:成熟的流處理框架可以提供潛在的支持,可用的庫,甚至開發問答幫助。選擇正確的平臺會在這方面提供很大的幫助。
運行時和編程模型
運行時和編程模型是一個系統最重要的特質,因為它們定義了表達方式、可能的操作和將來的局限性。因此,運行時和編程模型決定了系統的能力和適用場景。
實現流處理系統有兩種完全不同的方式:一種是稱作原生流處理,意味著所有輸入的記錄一旦到達即會一個接著一個進行處理。
第二種稱為微批處理。把輸入的數據按照某種預先定義的時間間隔(典型的是幾秒鐘)分成短小的批量數據,流經流處理系統。
兩種方法都有其先天的優勢和不足。首先以原生流處理開始,原生流處理的優勢在于它的表達方式。數據一旦到達立即處理,這些系統的延遲性遠比其它微批處理要好。除了延遲性外,原生流處理的狀態操作也容易實現,后續將詳細講解。
一般原生流處理系統為了達到低延遲和容錯性會花費比較大的成本,因為它需要考慮每條記錄。原生流處理的負載均衡也是個問題。比如,我們處理的數據按key分區,如果分區的某個key是資源密集型,那這個分區很容易成為作業的瓶頸。
接下來看下微批處理。將流式計算分解成一系列短小的批處理作業,也不可避免的減弱系統的表達力。像狀態管理或者join等操作的實現會變的困難,因為微批處理系統必須操作整個批量數據。并且,batch interval會連接兩個不易連接的事情:基礎屬性和業務邏輯。
相反地,微批處理系統的容錯性和負載均衡實現起來非常簡單,因為微批處理系統僅發送每批數據到一個worker節點上,如果一些數據出錯那就使用其它副本。微批處理系統很容易建立在原生流處理系統之上。
編程模型一般分為組合式和聲明式。組合式編程提供基本的構建模塊,它們必須緊密結合來創建拓撲。新的組件經常以接口的方式完成。相對應地,聲明式API操作是定義的高階函數。它允許我們用抽象類型和方法來寫函數代碼,并且系統創建拓撲和優化拓撲。聲明式API經常也提供更多高級的操作(比如,窗口函數或者狀態管理)。后面很快會給出樣例代碼。
主流流處理系統
有一系列各種實現的流處理框架,不能一一列舉,這里僅選出主流的流處理解決方案,并且支持Scala API。因此,我們將詳細介紹Apache Storm,Trident,Spark Streaming,Samza和Apache Flink。前面選擇講述的雖然都是流處理系統,但它們實現的方法包含了各種不同的挑戰。這里暫時不講商業的系統,比如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。
最后來介紹Apache Flink。Flink是個相當早的項目,開始于2008年,但只在最近才得到注意。Flink是原生的流處理系統,提供high level的API。Flink也提供API來像Spark一樣進行批處理,但兩者處理的基礎是完全不同的。Flink把批處理當作流處理中的一種特殊情況。在Flink中,所有的數據都看作流,是一種很好的抽象,因為這更接近于現實世界。
快速的介紹流處理系統之后,讓我們以下面的表格來更好清晰的展示它們之間的不同:
Word Count
Wordcount之于流處理框架學習,就好比hello world之于編程語言學習。它能很好的展示各流處理框架的不同之處,讓我們從Storm開始看看如何實現Wordcount:
?
首先,定義topology。第二行代碼定義一個spout,作為數據源。然后是一個處理組件bolt,分割文本為單詞。接著,定義另一個bolt來計算單詞數(第四行代碼)。也可以看到魔數5,8和12,這些是并行度,定義集群每個組件執行的獨立線程數。第八行到十五行是實際的WordCount bolt實現。因為Storm不支持內建的狀態管理,所有這里定義了一個局部狀態。
按之前描述,Trident是對Storm的一個更高層次的抽象,Trident最大的特點以batch的形式進行流處理。除了其它優勢,Trident提供了狀態管理,這對wordcount實現非常有用。
?
如你所見,上面代碼使用higher level操作,比如each(第七行代碼)和groupby(第八行代碼)。并且使用Trident管理狀態來存儲單詞數(第九行代碼)。
下面是時候祭出提供聲明式API的Apache Spark。記住,相對于前面的例子,這些代碼相當簡單,幾乎沒有冗余代碼。下面是簡單的流式計算單詞數:
?
每個Spark Streaming的作業都要有StreamingContext,它是流式函數的入口。StreamingContext加載第一行代碼定義的配置conf,但更重要地,第二行代碼定義batch interval(這里設置為1秒)。第六行到八行代碼是整個單詞數計算。這些是標準的函數式代碼,Spark定義topology并且分布式執行。第十二行代碼是每個Spark Streaming作業最后的部分:啟動計算。記住,Spark Streaming作業一旦啟動即不可修改。接下來看下Apache Samza,另外一個組合式API例子:
?
Samza的屬性配置文件定義topology,為了簡明這里并沒把配置文件放上來。定義任務的輸入和輸出,并通過Kafka topic通信。在單詞數計算整個topology是WordCountTask。在Samza中,實現特殊接口定義組件StreamTask,在第三行代碼重寫方法process。它的參數列表包含所有連接其它系統的需要。第八行到十行簡單的Scala代碼是計算本身。Flink的API跟Spark Streaming是驚人的相似,但注意到代碼里并未設置batch interval。
?
上面的代碼是相當的直白,僅僅只是幾個函數式調用,Flink支持分布式計算。
結論
上面給出了基本的理論和主流流處理框架介紹,下篇文章將會更深入的探討其它關注點。希望你能對前面的文章感興趣。
End.
?