1. 程式人生 > >Storm介紹及與Spark Streaming對比

Storm介紹及與Spark Streaming對比

1 Storm介紹

Storm是由Twitter開源的分散式、高容錯的實時處理系統,它的出現令持續不斷的流計算變得容易,彌補了Hadoop批處理所不能滿足的實時要求。Storm常用於在實時分析、線上機器學習、持續計算、分散式遠端呼叫和ETL等領域。

在Storm的叢集裡面有兩種節點:控制節點(Master Node)和工作節點(Worker Node)。控制節點上面執行一個名為Nimbus的程序,它用於資源分配和狀態監控;每個工作節點上面執行一個Supervisor的程序,它會監聽分配給它所在機器的工作,根據需要啟動/關閉工作程序。Storm叢集架構如下圖所示:

clip_image002

圖 1    Storm叢集架構

Storm叢集中每個元件具體描述如下:

l  Nimbus:負責在叢集裡面傳送程式碼,分配工作給機器並且監控狀態,在叢集中只有一個,作用類似Hadoop裡面的JobTracker。

l  ZooKeeper:Storm重點依賴的外部資源,Nimbus、Supervisor和Worker等都是把心跳資料儲存在ZooKeeper上,Nimbus也是根據ZooKeeper上的心跳和任務執行狀況進行排程和任務分配的。

l  Supervisor:在執行節點上,監聽分配的任務,根據需要啟動或關閉工作程序Worker。每一個要執行Storm的機器上都執行一個Supervisor,並且按照機器的配置設定上面分配的槽位數。

l  Worker:在Supervisor上建立的一個JVM例項,Worker中執行Executor,而Executor作為Task執行的容器。

l  Executor:執行時Task所在的直接容器,在Executor中執行Task的處理邏輯。一個或多個Executor例項可以執行在同一個Worker程序中,一個或多個Task可以運行於同一個Executor中;在Worker程序並行的基礎上,Executor可以並行,進而Task也能夠基於Executor實現平行計算

l  Task:Spout/Bolt在執行時所表現出來的實體,都稱為Task,一個Spout/Bolt在執行時可能對應一個或多個Spout Task或Bolt Task,與實際在編寫Topology時進行配置有關。在Storm0.8之後,Task不再與物理執行緒對應,同一個Spout Task或Bolt Task可能會共享一個物理執行緒,該執行緒稱為Executor。

Storm提交執行的程式稱為Topology,它處理的最小的訊息單位是一個Tuple,也就是一個任意物件的陣列。Topology由Spout和Bolt構成,Spout是發出Tuple的結點,Bolt可以隨意訂閱某個Spout或者Bolt發出的Tuple。下圖是一個Topology設計的邏輯圖的例子:

clip_image004

圖 2    Topology設計的邏輯圖

Topology: Topology概念類似於Hadoop中的MapReduce作業,是一個用來編排、容納一組計算邏輯元件(Spout、Bolt)的物件(Hadoop MapReduce中一個作業包含一組Map任務、Reduce任務),這一組計算元件可以按照DAG圖的方式編排起來(通過選擇Stream Groupings來控制資料流分發流向),從而組合成一個計算邏輯更加負責的物件,那就是Topology。一個Topology執行以後就不能停止,它會無限地執行下去,除非手動干預(顯式執行bin/storm kill)或意外故障(如停機、整個Storm叢集掛掉)讓它終止。

Spout: Spout是一個Topology的訊息生產的源頭,Spout是一個持續不斷生產訊息的元件,例如,它可以是一個Socket Server在監聽外部Client連線併發送訊息、可以是一個訊息佇列(MQ)的消費者、可以是用來接收Flume Agent的Sink所傳送訊息的服務,等等。Spout生產的訊息在Storm中被抽象為Tuple,在整個Topology的多個計算元件之間都是根據需要抽象構建的Tuple訊息來進行連線,從而形成流。

Bolt:Storm中訊息的處理邏輯被封裝到Bolt元件中,任何處理邏輯都可以在Bolt裡面執行,處理過程和普通計算應用程式沒什麼區別,只是需要根據Storm的計算語義來合理設定一下元件之間訊息流的宣告、分發和連線即可。Bolt可以接收來自一個或多個Spout的Tuple訊息,也可以來自多個其它Bolt的Tuple訊息,也可能是Spout和其它Bolt組合傳送的Tuple訊息。

Stream Grouping:Storm中用來定義各個計算元件(Spout和Bolt)之間流的連線、分組和分發關係。Storm定義瞭如下7種分發策略:Shuffle Grouping(隨機分組)、Fields Grouping(按欄位分組)、All Grouping(廣播分組)、Global Grouping(全域性分組)、Non Grouping(不分組)、Direct Grouping(直接分組)、Local or Shuffle Grouping(本地/隨機分組),各種策略的具體含義可以參考Storm官方文件、比較容易理解。

在Storm中可以通過元件簡單序列或者組合多種流操作處理資料:

Storm元件簡單序列

這種方式是最簡單最直觀的,只要我們將Storm的元件(Spout或Bolt)序列起來即可實現,只需要瞭解編寫這些元件的基本方法即可。在實際應用中,如果我們需要從某一個數據源連續地接收訊息,然後順序地處理每一個請求,就可以使用這種序列方式來處理。如果說處理單元的邏輯非常複雜,那麼就需要處理邏輯進行分離,屬於同一類操作的邏輯封裝到一個處理元件中,做到各個元件之間弱耦合。

clip_image006

圖 3     Storm元件簡單序列

Storm組合多種流操作

Storm支援流聚合操作,將多個元件的資料匯聚到同一個處理元件來統一處理,可以實現對多個Spout元件通過流聚合到一個Bolt元件(Sout到Bolt的多對一、多對多操作),也可以實現對多個Bolt通過流聚合到另一個Bolt元件(Bolt到Bolt的多對一、多對多操作)。

clip_image008

圖 4     Storm組合多種流操作

下圖是Topology的提交流程圖:

clip_image010 

圖 5     Topology的提交流程圖

1.     客戶端通過Nimbus的介面上傳程式jar包到Nimbus的Inbox目錄中,上傳結束後,通過提交方法向Nimbus提交一個Topology。

2.     Nimbus接收到提交Topology的命令後,對接收到的程式jar包進行序列化,把序列化的結果放到Nimbus節點的stormdist目錄中,同時把當前Storm執行的配置生成一個stormconf.ser檔案也放到該目錄中。靜態的資訊設定完成後,通過心跳資訊分配任務到機器節點。在設定Topology所關聯的Spouts和Bolts時,可以同時設定當前Spout和Bolt的Executor數目和Task數目,預設情況下,一個Topology的Task的總和與Executor的總和一致。之後,系統根據Worker的數目,儘量平均的分配這些Task的執行。其中Worker在哪個Supervisor節點上執行是由Storm本身決定的。

3.     任務分配好之後,Nimbus節點會將任務的資訊提交到ZooKeeper叢集,同時在ZooKeeper叢集中會有Worker分派節點,這裡儲存了當前Topology的所有Worker程序的心跳資訊。

4.     Supervisor節點會不斷的輪詢ZooKeeper叢集,在ZooKeeper的分派節點中儲存了所有Topology的任務分配資訊、程式碼儲存目錄和任務之間的關聯關係等,Supervisor通過輪詢此節點的內容,來領取自己的任務,啟動Worker程序執行。

5.     一個Topology執行之後,就會不斷的通過Spout來發送Stream流,通過Bolt來不斷的處理接收到的資料流。

2 Spark Streaming與Storm比較

Storm和Spark Streaming都是分散式流處理的開源框架,但是它們之間還是有一些區別的,這裡將進行比較並指出它們的重要的區別。

1.     處理模型以及延遲

雖然這兩個框架都提供可擴充套件性(Scalability)和可容錯性(Fault Tolerance),但是它們的處理模型從根本上說是不一樣的。Storm處理的是每次傳入的一個事件,而Spark Streaming是處理某個時間段視窗內的事件流。因此,Storm處理一個事件可以達到亞秒級的延遲,而Spark Streaming則有秒級的延遲。

2.     容錯和資料保證

在容錯資料保證方面的權衡方面,Spark Streaming提供了更好的支援容錯狀態計算。在Storm中,當每條單獨的記錄通過系統時必須被跟蹤,所以Storm能夠至少保證每條記錄將被處理一次,但是在從錯誤中恢復過來時候允許出現重複記錄,這意味著可變狀態可能不正確地被更新兩次。而Spark Streaming只需要在批處理級別對記錄進行跟蹤處理,因此可以有效地保證每條記錄將完全被處理一次,即便一個節點發生故障。雖然Storm的 Trident library庫也提供了完全一次處理的功能。但是它依賴於事務更新狀態,而這個過程是很慢的,並且通常必須由使用者實現。

簡而言之,如果你需要亞秒級的延遲,Storm是一個不錯的選擇,而且沒有資料丟失。如果你需要有狀態的計算,而且要完全保證每個事件只被處理一次,Spark Streaming則更好。Spark Streaming程式設計邏輯也可能更容易,因為它類似於批處理程式,特別是在你使用批次(儘管是很小的)時。

3.     實現和程式設計API

Storm主要是由Clojure語言實現,Spark Streaming是由Scala實現。如果你想看看這兩個框架是如何實現的或者你想自定義一些東西你就得記住這一點。Storm是由BackType和 Twitter開發,而Spark Streaming是在UC Berkeley開發的。

Storm提供了Java API,同時也支援其他語言的API。 Spark Streaming支援Scala和Java語言(其實也支援Python)。另外Spark Streaming的一個很棒的特性就是它是在Spark框架上執行的。這樣你就可以想使用其他批處理程式碼一樣來寫Spark Streaming程式,或者是在Spark中互動查詢。這就減少了單獨編寫流批量處理程式和歷史資料處理程式。

4.     生產支援

Storm已經出現好多年了,而且自從2011年開始就在Twitter內部生產環境中使用,還有其他一些公司。而Spark Streaming是一個新的專案,並且在2013年僅僅被Sharethrough使用(據作者瞭解)。

Storm是 Hortonworks Hadoop資料平臺中流處理的解決方案,而Spark Streaming出現在 MapR的分散式平臺和Cloudera的企業資料平臺中。除此之外,Databricks是為Spark提供技術支援的公司,包括了Spark Streaming。

5.     叢集管理整合

儘管兩個系統都執行在它們自己的叢集上,Storm也能執行在Mesos,而Spark Streaming能執行在YARN 和 Mesos上。