Storm介紹(一)

Storm介紹(一)

轉載:https://www.cnblogs.com/Jack47/p/storm_intro-1.htmlhtml

內容簡介

本文是Storm系列之一,介紹了Storm的起源,Storm做者的八卦,Storm的特色和Storm模型的基本原理,着重介紹了Storm中的基本概念(Spout, Bolt, Stream, Tuple等)和對應的編程接口,能夠做爲Storm的入門文檔來閱讀。java

八卦

以前的技術文章都寫的有點一板一眼,太正經了。今天在文章正式開始前,跟你們八卦一下Storm的做者Nathan Marz吧。web

Storm的做者是Nathan Marz,Nathan Marz在BackType公司工做的時候有了Storm的點子並獨自一人實現了Storm。在2011年Twitter準備收購BackType之際,Nathan Marz爲了提升Twitter對BackType的估值,在一篇博客裏向外界介紹了Storm。Twitter對這項技術很是感興趣,所以在Twitter收購BackType的時候Storm發揮了重大做用。後來Nathan Marz開源Storm時,也藉着Twitter的品牌影響力而讓Storm名聲大震!算法

Storm的特色之一是可靠的消息處理機制,這個機制中最重要的一環是設計一個算法來跟蹤Storm中處理的數據,確保Storm知道消息是否被完整的處理。他創造出的這個算法,極大的簡化了系統的設計。Nathan Marz說這算法是他職業生涯中開發的最出色的算法之一,也說明了受過良好的計算機科學的教育是很是重要的。有趣的是發明這個算法的那天,正好是他和不久前遇到的一個姑娘約會的日子。當天由於發明了這個算法而很是興奮,致使他心思一直在這個算法上,毫無疑問就搞砸了和這個姑娘的約會!數據庫

Storm是什麼

Storm官方網站有段簡介apache

Storm是一個免費並開源的分佈式實時計算系統。利用Storm能夠很容易作到可靠地處理無限的數據流,像Hadoop批量處理大數據同樣,Storm能夠實時處理數據。Storm簡單,可使用任何編程語言。編程

在Storm以前,進行實時處理是很是痛苦的事情: 須要維護一堆消息隊列和消費者,他們構成了很是複雜的圖結構。消費者進程從隊列裏取消息,處理完成後,去更新數據庫,或者給其餘隊列發新消息。api

這樣進行實時處理是很是痛苦的。咱們主要的時間都花在關注往哪裏發消息,從哪裏接收消息,消息如何序列化,真正的業務邏輯只佔了源代碼的一小部分。一個應用程序的邏輯運行在不少worker上,但這些worker須要各自單獨部署,還須要部署消息隊列。最大問題是系統很脆弱,並且不是容錯的:須要本身保證消息隊列和worker進程工做正常。數組

Storm完整地解決了這些問題。它是爲分佈式場景而生的,抽象了消息傳遞,會自動地在集羣機器上併發地處理流式計算,讓你專一於實時處理的業務邏輯。安全

Storm的特色

Storm有以下特色:

  1. 編程簡單:開發人員只須要關注應用邏輯,並且跟Hadoop相似,Storm提供的編程原語也很簡單
  2. 高性能,低延遲:能夠應用於廣告搜索引擎這種要求對廣告主的操做進行實時響應的場景。
  3. 分佈式:能夠輕鬆應對數據量大,單機搞不定的場景
  4. 可擴展: 隨着業務發展,數據量和計算量愈來愈大,系統可水平擴展
  5. 容錯:單個節點掛了不影響應用
  6. 消息不丟失:保證消息處理

不過Storm不是一個完整的解決方案。使用Storm時你須要關注如下幾點:

  1. 若是使用的是本身的消息隊列,須要加入消息隊列作數據的來源和產出的代碼
  2. 須要考慮如何作故障處理:如何記錄消息隊列處理的進度,應對Storm重啓,掛掉的場景
  3. 須要考慮如何作消息的回退:若是某些消息處理一直失敗怎麼辦?

Storm的應用

跟Hadoop不同,Storm是沒有包括任何存儲概念的計算系統。這就讓Storm能夠用在多種不一樣的場景下:非傳統場景下數據動態到達或者數據存儲在數據庫這樣的存儲系統裏(或數據是被實時操控其餘設備的控制器(如交易系統)所消費)

Storm有不少應用:實時分析,在線機器學習(online machine learning),連續計算(continuous computation),分佈式遠程過程調用(RPC)、ETL等。Storm處理速度很快:每一個節點每秒鐘能夠處理超過百萬的數據組。它是可擴展(scalable),容錯(fault-tolerant),保證你的數據會被處理,而且很容易搭建和操做。

例如Nathan Marz提供的例子,產生Twitter的趨勢信息。Twitter從海量推文中抽取趨勢信息,並在本地區域和國家層級進行維護。這意味者一旦一個案例開始出現,Twitter的話題趨勢算法就能實時的鑑別出這個話題。這個實時的算法就是經過在Storm上連續分析Twitter數據來實現的。

其餘開源的大數據解決方案

下表列出了一組開源的大數據解決方案,包括傳統的批處理和流式處理的應用程序。

解決方案 開發者 類型 描述
Storm Twitter 流式處理 Twitter的流式處理大數據分析方案
S4 Yahoo! 流式處理 Yahoo!的分佈式流式計算平臺
Hadoop Apache 批處理 MapReduce範式的第一個開源實現
Spark UC Berkeley AMPLab 批處理 支持內存數據集和彈性恢復的分析平臺

Yahoo! S4和Storm之間的關鍵差異是Storm在故障的狀況下能夠保證消息的處理,而S4可能會丟消息。

Hadoop無疑是大數據分析的王者,本質上是一個批量處理系統,它專一於大數據的批量處理。數據存儲在Hadoop 文件系統裏(HDFS)並在處理的時候分發到集羣中的各個節點。當處理完成,產出的數據放回到HDFS上。在Storm上構建的拓撲處理的是持續不斷的流式數據。不一樣於Hadoop的任務,這些處理過程不會終止,會持續處理到達的數據。

Hadoop處理的是靜態的數據,而Storm處理的是動態的、連續的數據。Twitter的用戶天天都會發上千萬的推,因此這種處理技術是很是有用的。Storm不只僅是一個傳統的大數據分析系統:它是一個復瑣事件(complex event-processing)處理系統的例子。復瑣事件處理系統一般是面向檢測和計算的,這兩部分均可以經過用戶定義的算法在Storm中實現。例如,復瑣事件處理能夠用來從大量的事件中區分出有意義的事件,而後對這些事件實時處理。

Storm模型

Storm實現了一個數據流(data flow)的模型,在這個模型中數據持續不斷地流經一個由不少轉換實體構成的網絡。一個數據流的抽象叫作流(stream),流是無限的元組(Tuple)序列。元組就像一個能夠表示標準數據類型(例如int,float和byte數組)和用戶自定義類型(須要額外序列化代碼的)的數據結構。每一個流由一個惟一的ID來標示的,這個ID能夠用來構建拓撲中各個組件的數據源。

以下圖所示,其中的水龍頭表明了數據流的來源,一旦水龍頭打開,數據就會源源不斷地流經Bolt而被處理。圖中有三個流,用不一樣的顏色來表示,每一個數據流中流動的是元組(Tuple),它承載了具體的數據。元組經過流經不一樣的轉換實體而被處理。

Storm對數據輸入的來源和輸出數據的去向沒有作任何限制。像Hadoop,是須要把數據放到本身的文件系統HDFS裏的。在Storm裏,可使用任意來源的數據輸入和任意的數據輸出,只要你實現對應的代碼來獲取/寫入這些數據就能夠。典型場景下,輸入/輸出數據來是基於相似Kafka或者ActiveMQ這樣的消息隊列,可是數據庫,文件系統或者web服務也都是能夠的。

topology

概念

Storm中涉及的主要概念有:

  1. 拓撲(Topologies)
  2. 元組(Tuple)
  3. 流(Streams)
  4. Spouts(噴嘴)
  5. Bolts
  6. 任務(Tasks)
  7. 組件(Component)
  8. 流分組(Stream groupings)
  9. 可靠性(Reliability)
  10. Workers(工做進程)

能夠看到Storm中各個概念的名字起的很是好,也很形象。

拓撲(Topologies)

一個Storm拓撲打包了一個實時處理程序的邏輯。一個Storm拓撲跟一個MapReduce的任務(job)是相似的。主要區別是MapReduce任務最終會結束,而拓撲會一直運行(固然直到你殺死它)。一個拓撲是一個經過流分組(stream grouping)把Spout和Bolt鏈接到一塊兒的拓撲結構。圖的每條邊表明一個Bolt訂閱了其餘Spout或者Bolt的輸出流。一個拓撲就是一個複雜的多階段的流計算。

資源

元組(Tuple)

元組是Storm提供的一個輕量級的數據格式,能夠用來包裝你須要實際處理的數據。元組是一次消息傳遞的基本單元。一個元組是一個命名的值列表,其中的每一個值均可以是任意類型的。元組是動態地進行類型轉化的--字段的類型不須要事先聲明。在Storm中編程時,就是在操做和轉換由元組組成的流。一般,元組包含整數,字節,字符串,浮點數,布爾值和字節數組等類型。要想在元組中使用自定義類型,就須要實現本身的序列化方式。

資源

流(Streams)

流是Storm中的核心抽象。一個流由無限的元組序列組成,這些元組會被分佈式並行地建立和處理。經過流中元組包含的字段名稱來定義這個流。
每一個流聲明時都被賦予了一個ID。只有一個流的Spout和Bolt很是常見,因此OutputFieldsDeclarer提供了不須要指定ID來聲明一個流的函數(Spout和Bolt都須要聲明輸出的流)。這種狀況下,流的ID是默認的「default」。

資源

Spouts

Spout(噴嘴,這個名字很形象)是Storm中流的來源。一般Spout從外部數據源,如消息隊列中讀取元組數據並吐到拓撲裏。Spout能夠是可靠的(reliable)或者不可靠(unreliable)的。可靠的Spout可以在一個元組被Storm處理失敗時從新進行處理,而非可靠的Spout只是吐數據到拓撲裏,不關心處理成功仍是失敗了。

Spout能夠一次給多個流吐數據。此時須要經過OutputFieldsDeclarerdeclareStream函數來聲明多個流並在調用SpoutOutputCollector提供的emit方法時指定元組吐給哪一個流。

Spout中最主要的函數是nextTuple,Storm框架會不斷調用它去作元組的輪詢。若是沒有新的元組過來,就直接返回,不然把新元組吐到拓撲裏。nextTuple必須是非阻塞的,由於Storm在同一個線程裏執行Spout的函數。

Spout中另外兩個主要的函數是ackfail。當Storm檢測到一個從Spout吐出的元組在拓撲中成功處理完時調用ack,沒有成功處理完時調用fail。只有可靠型的Spout會調用ackfail函數。更多細節能夠查看Storm Java文檔和個人另一篇文章:Storm如何保證可靠的消息處理

Bolts

在拓撲中全部的計算邏輯都是在Bolt中實現的。一個Bolt能夠處理任意數量的輸入流,產生任意數量新的輸出流。Bolt能夠作函數處理,過濾,流的合併,聚合,存儲到數據庫等操做。Bolt就是流水線上的一個處理單元,把數據的計算處理過程合理的拆分到多個Bolt、合理設置Bolt的task數量,可以提升Bolt的處理能力,提高流水線的併發度。

Bolt能夠給多個流吐出元組數據。此時須要使用OutputFieldsDeclarerdeclareStream方法來聲明多個流並在使用[OutputColletor](https://storm.apache.org/javadoc/apidocs/backtype/storm/task/OutputCollector.html)emit方法時指定給哪一個流吐數據。

當你聲明瞭一個Bolt的輸入流,也就訂閱了另一個組件的某個特定的輸出流。若是但願訂閱另外一個組件的全部流,須要單獨挨個訂閱。InputDeclarer有語法糖來訂閱ID爲默認值的流。例如declarer.shuffleGrouping("redBolt")訂閱了redBolt組件上的默認流,跟declarer.shuffleGrouping("redBolt", DEFAULT_STREAM_ID)是相同的。

在Bolt中最主要的函數是execute函數,它使用一個新的元組看成輸入。Bolt使用OutputCollector對象來吐出新的元組。Bolts必須爲處理的每一個元組調用OutputCollectorack方法以便於Storm知道元組何時被各個Bolt處理完了(最終就能夠確認Spout吐出的某個元組處理完了)。一般處理一個輸入的元組時,會基於這個元組吐出零個或者多個元組,而後確認(ack)輸入的元組處理完了,Storm提供了IBasicBolt接口來自動完成確認。

必須注意OutputCollector不是線程安全的,因此全部的吐數據(emit)、確認(ack)、通知失敗(fail)必須發生在同一個線程裏。更多信息能夠參照問題定位

資源

任務(Tasks)

每一個Spout和Bolt會以多個任務(Task)的形式在集羣上運行。每一個任務對應一個執行線程,流分組定義瞭如何從一組任務(同一個Bolt)發送元組到另一組任務(另一個Bolt)上。能夠在調用TopologyBuildersetSpoutsetBolt函數時設置每一個Spout和Bolt的併發數。

組件(Component)

組件(component)是對Bolt和Spout的統稱

流分組(Stream Grouping)

定義拓撲的時候,一部分工做是指定每一個Bolt應該消費哪些流。流分組定義了一個流在一個消費它的Bolt內的多個任務(task)之間如何分組。流分組跟計算機網絡中的路由功能是相似的,決定了每一個元組在拓撲中的處理路線。

在Storm中有七個內置的流分組策略,你也能夠經過實現CustomStreamGrouping接口來自定義一個流分組策略:

  1. 洗牌分組(Shuffle grouping): 隨機分配元組到Bolt的某個任務上,這樣保證同一個Bolt的每一個任務都可以獲得相同數量的元組。
  2. 字段分組(Fields grouping): 按照指定的分組字段來進行流的分組。例如,流是用字段「user-id"來分組的,那有着相同「user-id"的元組就會分到同一個任務裏,可是有不一樣「user-id"的元組就會分到不一樣的任務裏。這是一種很是重要的分組方式,經過這種流分組方式,咱們就能夠作到讓Storm產出的消息在這個"user-id"級別是嚴格有序的,這對一些對時序敏感的應用(例如,計費系統)是很是重要的。
  3. Partial Key grouping: 跟字段分組同樣,流也是用指定的分組字段進行分組的,可是在多個下游Bolt之間是有負載均衡的,這樣當輸入數據有傾斜時能夠更好的利用資源。這篇論文很好的解釋了這是如何工做的,有哪些優點。
  4. All grouping: 流會複製給Bolt的全部任務。當心使用這種分組方式。在拓撲中,若是但願某類元祖發送到全部的下游消費者,就可使用這種All grouping的流分組策略。
  5. Global grouping: 整個流會分配給Bolt的一個任務。具體一點,會分配給有最小ID的任務。
  6. 不分組(None grouping): 說明不關心流是如何分組的。目前,None grouping等價於洗牌分組。
  7. Direct grouping:一種特殊的分組。對於這樣分組的流,元組的生產者決定消費者的哪一個任務會接收處理這個元組。只能在聲明作直連的流(direct streams)上聲明Direct groupings分組方式。只能經過使用emitDirect系列函數來吐元組給直連流。一個Bolt能夠經過提供的TopologyContext來得到消費者的任務ID,也能夠經過OutputCollector對象的emit函數(會返回元組被髮送到的任務的ID)來跟蹤消費者的任務ID。在ack的實現中,Spout有兩個直連輸入流,ack和ackFail,使用了這種直連分組的方式。
  8. Local or shuffle grouping:若是目標Bolt在同一個worker進程裏有一個或多個任務,元組就會經過洗牌的方式分配到這些同一個進程內的任務裏。不然,就跟普通的洗牌分組同樣。這種方式的好處是能夠提升拓撲的處理效率,由於worker內部通訊就是進程內部通訊了,相比拓撲間的進程間通訊要高效的多。worker進程間通訊是經過使用Netty來進行網絡通訊的。

資源

  • TopologyBuilder: 使用這個類來定義拓撲
  • InputDeclarer: 當調用TopologyBuildersetBolt函數時會返回這個對象,它用來聲明一個Bolt的輸入流並指定流的分組方式。
  • CoordinatedBolt: 這個Bolt對於分佈式的RPC拓撲頗有用,大量使用了直連流(direct streams)和直連分組(direct groupings)

可靠性(Reliability)

Storm保證了拓撲中Spout產生的每一個元組都會被處理。Storm是經過跟蹤每一個Spout所產生的全部元組構成的樹形結構並得知這棵樹什麼時候被完整地處理來達到可靠性。每一個拓撲對這些樹形結構都有一個關聯的「消息超時」。若是在這個超時時間裏Storm檢測到Spout產生的一個元組沒有被成功處理完,那Sput的這個元組就處理失敗了,後續會從新處理一遍。

爲了發揮Storm的可靠性,須要你在建立一個元組樹中的一條邊時告訴Storm,也須要在處理完每一個元組以後告訴Storm。這些都是經過Bolt吐元組數據用的OutputCollector對象來完成的。標記是在emit函數裏完成,完成一個元組後須要使用ack函數來告訴Storm。

這些都在「保證消息處理」一文中會有更詳細的介紹。

Workers(工做進程)

拓撲以一個或多個Worker進程的方式運行。每一個Worker進程是一個物理的Java虛擬機,執行拓撲的一部分任務。例如,若是拓撲的併發設置成了300,分配了50個Worker,那麼每一個Worker執行6個任務(做爲Worker內部的線程)。Storm會盡可能把全部的任務均分到全部的Worker上。

資源

  • Config.TOPOLOGY_WORKERS: 這個配置設置了執行拓撲時分配Worker的數量。

Storm中用到的技術

ZeroMQ 提供了可擴展環境下的傳輸層高效消息通訊,一開始Storm的內部通訊使用的是ZeroMQ,後來做者想把Storm移交給Apache開源基金會來管理,而ZeroMQ的許可證書跟Apache基金會的政策有衝突。在Storm中,Netty比ZeroMQ更加高效,並且提供了worker間通訊時的驗證機制,因此在Storm0.9中,就改用了Netty

Clojure Storm系統的實現語言。Clojure是由Rich Hicky做爲一種通用語言發明的,它衍生自Lisp語言,簡化了多線程編程。

Apache ZooKeeper Zookeeper是一個實現高可靠的分佈式協做的開源項目。Storm使用Zookeeper來協調集羣中的多個節點。

參考資料

Storm簡介 這是淘寶主搜索的技術博客,文章通俗易懂

History of Apache Storm and lessons learned 推薦你們讀一讀,是Storm做者Nathan Marz寫的,文章講述了Storm的構思、建立過程和Storm的市場營銷,溝通交流和社區開發的故事。

twitter storm --IBM developerworks

Process real-time big data with Twitter Storm

Preview of Storm

Spark, an alternative for fast data analytics

相關文章
相關標籤/搜索