天天看點

RabbitMQ技術詳解(轉)

RabbitMQ是什麼

定義

RabbitMQ是一個開源的

AMQP

實作,伺服器端用

Erlang

語言編寫,支援多種用戶端,如:Python、Ruby、.NET、Java、JMS、C、PHP、ActionScript、XMPP、STOMP等,支援AJAX。用于在

分布式系統

中存儲轉發消息,在易用性、擴充性、高可用性等方面表現不俗。

AMPQ

AMQP,即Advanced Message Queuing Protocol,進階消息隊列協定,是

應用層協定

的一個開放标準,為面向消息的中間件設計。消息中間件主要用于元件之間的解耦,消息的發送者無需知道消息使用者的存在,反之亦然。 

它可以使對應的用戶端(client)與對應的消息中間件(broker)進行互動。消息中間件從釋出者(publisher)那裡收到消息(釋出消息的應用,也稱為producer),然後将他們轉發給消費者(consumers,處理消息的應用)。由于AMQP是一個網絡協定,是以釋出者、消費者以及消息中間件可以部署到不同的實體機器上面。

雖然在同步消息通訊的世界裡有很多公開标準(如 COBAR的 IIOP ,或者是 SOAP 等),但是在異步消息進行中卻不是這樣,隻有大企業有一些商業實作(如微軟的 MSMQ ,IBM 的 Websphere MQ 等),是以,在 2006 年的 6 月,Cisco 、Redhat、iMatix 等聯合制定了 AMQP 的公開标準。

RabbitMQ是由RabbitMQ Technologies Ltd開發并且提供商業支援的。該公司在2010年4月被SpringSource(VMWare的一個部門)收購。在2013年5月被并入Pivotal。其實VMWare,Pivotal和EMC本質上是一家的。不同的是VMWare是獨立上市子公司,而Pivotal是整合了EMC的某些資源,現在并沒有上市。

同類産品

消息中間件是一種由消息傳送機制或消息隊列模式組成的中間件技術,利用高效可靠的消息傳遞機制進行平台無關的資料交流,并基于資料通信來進行分布式系統的內建。
Redis

是一個Key-Value的NoSQL資料庫,開發維護很活躍,雖然它是一個Key-Value資料庫存儲系統,但它本身支援MQ功能,是以完成可以當做一個輕量級的隊列服務來使用。對于RabbitMQ和Redis的入隊和出隊操作,各執行100萬次,每10萬次記錄一次執行時間。測試資料分為128Bytes、512Bytes、1K和10K四個不同大小的資料。實驗表明:入隊時,當資料比較小時,Redis的性能要高于RabbitMQ,而如否資料大小超過了10K,Redis則慢的無法忍受;出隊時,無論資料大小,Redis都表現出非常好的性能,而RabbitMQ的出隊性能則遠低于Redis。

MemcacheQ

持久化消息隊列(簡稱mcq)是一個輕量級的消息隊列,特性如下:

  • 簡單易用
  • 處理速度快
  • 多條隊列
  • 并發性能好
  • 與memcache的協定相容。意味着隻要裝了前者的extension即可,不需要額外的插件
  • 在zend framework中使用很友善
MSMQ

這是微軟的産品力唯一被認為有價值的東西。如果MSMQ能證明可以應對這種任務,他們将選擇使用它。

  • 關鍵是它并不複雜,除了接收和發送,沒有别的;它有一些硬性限制,比如最大消息體積是4MB。
  • 然而,通過和一些想MassTransit或NServiceBus這樣的軟體的連接配接,它完全可以解決這些問題。 
    RabbitMQ技術詳解(轉)
ZeroMQ

ZeroMQ是一個非常輕量級的消息系統,号稱最快的消息隊列系統,專門為高吞吐量/低延遲的場景開發,在金融界的應用中經常可以發現它。

  • 與RabbitMQ相比,ZeroMQ支援許多進階消息場景,能夠實作RabbitMQ不擅長的進階/複雜的隊列,但是你必須實作ZeroMQ架構中的各個塊(比如Socket或Device等)。
  • ZeroMQ具有一個獨特的非中間件的模式,你不需要安裝和運作一個消息伺服器或中間件,因為你的應用程式将扮演這個服務角色。你隻需要簡單地引用ZeroMQ程式庫,可以使用NuGet安裝,然後你就可以愉快地在應用程式之間發送消息了。
  • 但是ZeroMQ僅提供非持久性的隊列,即沒有地方可以觀察它是否有問題出現,也就是說如果down機,資料将會丢失。
  • ZeroMQ非常靈活,但是你必須學習它的80頁的手冊(如果你要寫一個分布式系統,一定要閱讀它)。 
    RabbitMQ技術詳解(轉)
Jafka/Kafka

Kafka(能将消息分散到不同的節點上)是LinkedIn于2010年12月開發并開源的一個分布式MQ系統,現在是Apache的一個孵化項目,是一個高性能跨語言分布式Publish/Subscribe消息隊列系統,而Jafka是在Kafka之上孵化而來的,即Kafka的一個更新版。具有以下特性:

  • 快速持久化,可以在O(1)的系統開銷下進行消息持久化;
  • 高吞吐,在一台普通的伺服器上既可以打到10W/s的吞吐速率;
  • 完全的分布式系統,Broker、Producer、Consumer都原生自動支援分布式,自動實作複雜均衡;
  • 支援Hadoop資料并行加載,統一了線上和離線的消息處理,對于像Hadoop一樣的日志資料和離線分析系統,但又要求實時處理的限制,這是一個可行的解決方案。
  • 相對于ActiveMQ是一個非常輕量級的消息系統,除了性能非常好之外,還是一個工作良好的分布式系統。 
    RabbitMQ技術詳解(轉)
Apache ActiveMQ

ActiveMQ居于(RabbitMQ&ZeroMQ)之間,類似于ZemoMQ,它可以部署于代理模式和P2P模式。

  • ActiveMQ被譽為Java世界的中堅力量。它有很長的曆史,且被廣泛使用。它還是跨平台的,給那些非微軟平台的産品提供了一個天然的內建接入點。
  • 然而它隻有跑過了MSMQ才有可能被考慮。如需配置ActiveMQ則需要在目标機器上安裝Java環境。
  • 類似于RabbitMQ,它易于實作進階場景,而且隻需付出低消耗。它被譽為消息中間件的“瑞士軍刀”。 
    RabbitMQ技術詳解(轉)
RabbitMQ

RabbitMQ是使用Erlang編寫的一個開源消息隊列,本身支援很多的協定:AMQP, XMPP, SMTP, STONP,也正是如此,使的它變的非常重量級,更适合于企業級的開發。

  • 它實作了代理(Broker)架構,意味着消息在發送到用戶端之前可以在中央節點上排隊。此特性使得RabbitMQ易于使用和部署,适宜于很多場景如路由、負載均衡或消息持久化等,用消息隊列隻需幾行代碼即可搞定。
  • 但是,這使得它的可擴充性差,速度較慢,因為中央節點增加了延遲,消息封裝後也比較大。
  • 如需配置RabbitMQ則需要在目标機器上安裝Erlang環境。 
    RabbitMQ技術詳解(轉)

總結

最終,上述同類産品:

  1. 都有各自用戶端API或支援多種程式設計語言
  2. 都有大量的文檔
  3. 都提供了積極的支援
  4. ActiveMQ、RabbitMQ、MSMQ、Redis都需要啟動服務程序,這些都可以監控和配置,其他幾個就有問題了
  5. 都相對提供了良好的可靠性(一緻性)、擴充性和負載均衡,當然還有性能

下面是網友的對四種消息隊列的具體測試結果,顯示的是發送和接受的每秒鐘的消息數,整個過程共産生1百萬條1K的消息,測試的執行是在WIndows Vista上進行的。(

有待自己驗證

) 

RabbitMQ技術詳解(轉)

如上圖所見,ZeroMQ和其他的不是一個級别,它的性能驚人的高。結論很清楚:如果希望一個應用程式發送消息越快越好,選擇ZeroMQ,并且在你不太在意偶然會丢失某些消息的情況下更有價值。

RabbitMQ為何會出現

或者說AMPQ為何會出現,它的應用場景又是什麼?

解決什麼問題

  • 你是否遇到過兩個(多個)系統間需要通過定時任務來同步某些資料?你是否在為異構系統的不同程序間互相調用、通訊的問題而苦惱、掙紮?
  • 在Web應用高并發環境下,由于來不及同步處理,請求往往會發生堵塞。比如說,大量的insert、update請求同時到達mysql,會帶來無數的行鎖表鎖,最後導緻請求數過多,觸發too many connections錯誤。

消息服務擅長于解決多系統、異構系統間的資料交換(消息通知/通訊)問題,你也可以把它用于系統間服務的互相調用(RPC)通過使用消息隊列,我們可以異步處理請求,進而緩解系統的壓力。

應用場景

對于一個大型的軟體系統來說,它會有很多的元件或者說子產品或者說子系統或者(Subsystem or Component or Submodule)。那麼這些子產品的如何通信?這和傳統的IPC有很大的差別。傳統的IPC很多都是在單一系統上的,子產品耦合性很大,不适合擴充(Scalability);如果使用socket那麼不同的子產品的确可以部署到不同的機器上,但是還是有很多問題需要解決。比如:

  1. 資訊的發送者和接收者如何維持這個連接配接,如果一方的連接配接中斷,這期間的資料如何方式丢失?
  2. 如何降低發送者和接收者的耦合度?
  3. 如何讓Priority高的接收者先接到資料?
  4. 如何做到Load balance?有效均衡接收者的負載?
  5. 如何有效的将資料發送到相關的接收者?也就是說将接收者subscribe 不同的資料,如何做有效的filter。
  6. 如何做到可擴充,甚至将這個通信子產品發到cluster上?
  7. 如何保證接收者接收到了完整,正确的資料?

AMDQ協定解決了以上的問題,而RabbitMQ實作了AMQP。

RabbitMQ基礎概念

應用場景架構

RabbitMQ技術詳解(轉)
  • RabbitMQ Server:也叫

    broker server

    ,它不是運送食物的卡車,而是一種傳輸服務。原話是RabbitMQ isn’t a food truck, it’s a delivery service. 他的角色就是維護一條從Producer到Consumer的路線,保證資料能夠按照指定的方式進行傳輸。但是這個保證也不是100%的保證,但是對于普通的應用來說這已經足夠了。當然對于商業系統來說,可以再做一層資料一緻性的guard,就可以徹底保證系統的一緻性了。
  • Client A & B:也叫

    Producer

    ,資料的發送方。Create messages and Publish (Send) them to a broker server (RabbitMQ)。一個Message有兩個部分:Payload(有效載荷)和Label(标簽)。Payload顧名思義就是傳輸的資料,Label是Exchange的名字或者說是一個tag,它描述了payload,而且RabbitMQ也是通過這個label來決定把這個Message發給哪個Consumer。AMQP僅僅描述了label,而RabbitMQ決定了如何使用這個label的規則。
  • Client 1,2,3:也叫

    Consumer

    ,資料的接收方。Consumers attach to a broker server (RabbitMQ) and subscribe to a queue。把queue比作是一個有名字的郵箱。當有Message到達某個郵箱後,RabbitMQ把它發送給它的某個訂閱者即Consumer。當然可能會把同一個Message發送給很多的Consumer。在這個Message中,隻有payload,label已經被删掉了。對于Consumer來說,它是不知道誰發送的這個資訊的。就是協定本身不支援。但是當然了如果Producer發送的payload包含了Producer的資訊就另當别論了。

對于一個資料從Producer到Consumer的正确傳遞,還有三個概念需要明确:exchanges, queues and bindings。

  • Exchanges are where producers publish their messages. 消息交換機,它指定消息按什麼規則,路由到哪個隊列
  • Queues are where the messages end up and are received by consumers. 消息隊列載體,每個消息都會被投入到一個或多個隊列
  • Bindings are how the messages get routed from the exchange to particular queues. 綁定,它的作用就是把exchange和queue按照路由規則綁定起來
  • Routing Key:路由關鍵字,exchange根據這個關鍵字進行消息投遞

還有幾個概念是上述圖中沒有标明的,那就是Connection(連接配接),Channel(通道,頻道),Vhost(虛拟主機)。

  • Connection:就是一個TCP的連接配接。Producer和Consumer都是通過TCP連接配接到RabbitMQ Server的。以後我們可以看到,程式的起始處就是建立這個TCP連接配接。
  • Channel:虛拟連接配接。它建立在上述的TCP連接配接中。資料流動都是在Channel中進行的。也就是說,一般情況是程式起始建立TCP連接配接,第二步就是建立這個Channel。
  • Vhost:虛拟主機,一個broker裡可以開設多個vhost,用作不同使用者的權限分離。每個virtual host本質上都是一個RabbitMQ Server,擁有它自己的queue,exchagne,和bings rule等等。這保證了你可以在多個不同的application中使用RabbitMQ。

Channel的選擇

那麼,為什麼使用Channel,而不是直接使用TCP連接配接?

對于OS來說,建立和關閉TCP連接配接是有代價的,頻繁的建立關閉TCP連接配接對于系統的性能有很大的影響,而且TCP的連接配接數也有限制,這也限制了系統處理高并發的能力。但是,在TCP連接配接中建立Channel是沒有上述代價的。對于Producer或者Consumer來說,可以并發的使用多個Channel進行Publish或者Receive。 

有實驗表明,1s的資料可以Publish10K的資料包。當然對于不同的硬體環境,不同的資料包大小這個資料肯定不一樣,但是我隻想說明,對于普通的Consumer或者Producer來說,這已經足夠了。如果不夠用,你考慮的應該是如何細化split你的設計。

消息隊列執行過程

  1. 用戶端連接配接到消息隊列伺服器,打開一個Channel。
  2. 用戶端聲明一個Exchange,并設定相關屬性。
  3. 用戶端聲明一個Queue,并設定相關屬性。
  4. 用戶端使用Routing key,在Exchange和Queue之間建立好綁定關系。
  5. 用戶端投遞消息到Exchange。

Exchange接收到消息後,就根據消息的key和已經設定的Binding,進行消息路由,将消息投遞到一個或多個隊列裡。有三種類型的Exchanges:direct,fanout,topic,每個實作了不同的路由算法(routing algorithm):

  • Direct exchange:完全根據key進行投遞的叫做Direct交換機。如果Routing key比對, 那麼Message就會被傳遞到相應的queue中。其實在queue建立時,它會自動的以queue的名字作為routing key來綁定那個exchange。例如,綁定時設定了Routing key為”abc”,那麼用戶端送出的消息,隻有設定了key為”abc”的才會投遞到隊列。
  • Fanout exchange:不需要key的叫做Fanout交換機。它采取廣播模式,一個消息進來時,投遞到與該交換機綁定的所有隊列。
  • Topic exchange:對key進行模式比對後進行投遞的叫做Topic交換機。比如符号”#”比對一個或多個詞,符号””比對正好一個詞。例如”abc.#”比對”abc.def.ghi”,”abc.”隻比對”abc.def”。

更多消息隊列相關設計介紹請參考:

  • RabbitMQ系列二(建構消息隊列)
  • RabbitMQ系列三 (深入消息隊列)

消息隊列的建立

Consumer和Procuder都可以通過 queue.declare 建立queue。對于某個Channel來說,Consumer不能declare一個queue,卻訂閱其他的queue。當然也可以建立私有的queue。這樣隻有app本身才可以使用這個queue。queue也可以自動删除,被标為auto-delete的queue在最後一個Consumer unsubscribe後就會被自動删除。那麼如果是建立一個已經存在的queue呢?那麼不會有任何的影響。需要注意的是沒有任何的影響,也就是說第二次建立如果參數和第一次不一樣,那麼該操作雖然成功,但是queue的屬性并不會被修改。

那麼誰應該負責建立這個queue呢?是Consumer,還是Producer?

如果queue不存在,當然Consumer不會得到任何的Message。但是如果queue不存在,那麼Producer Publish的Message會被丢棄。是以,還是為了資料不丢失,Consumer和Producer都try to create the queue!反正不管怎麼樣,這個接口都不會出問題。

Queue對load balance的處理是完美的。對于多個Consumer來說,RabbitMQ 使用循環的方式(round-robin)的方式均衡的發送給不同的Consumer。

消息的ack機制

預設情況下,如果Message 已經被某個Consumer正确的接收到了,那麼該Message就會被從queue中移除。當然也可以讓同一個Message發送到很多的Consumer。

如果一個queue沒被任何的Consumer Subscribe(訂閱),那麼,如果這個queue有資料到達,那麼這個資料會被cache,不會被丢棄。當有Consumer時,這個資料會被立即發送到這個Consumer,這個資料被Consumer正确收到時,這個資料就被從queue中删除。

那麼什麼是正确收到呢?通過ack。

  • 每個Message都要被acknowledged(确認,ack)。我們可以顯示的在程式中去ack(Consumer的basic.ack),也可以自動的ack(訂閱Queue時指定auto_ack為true)。
  • 如果有資料沒有被ack,那麼RabbitMQ Server會把這個資訊發送到下一個Consumer。
  • 如果這個app有bug,忘記了ack,那麼RabbitMQ Server不會再發送資料給它,因為Server認為這個Consumer處理能力有限。
  • 而且ack的機制可以起到限流的作用(Benefit to throttling):在Consumer處理完成資料後發送ack,甚至在額外的延時後發送ack,将有效的balance Consumer的load。

當然對于實際的例子,比如我們可能會對某些資料進行merge,比如merge 4s内的資料,然後sleep 4s後再擷取資料。特别是在監聽系統的state,我們不希望所有的state實時的傳遞上去,而是希望有一定的延時。這樣可以減少某些IO,而且終端使用者也不會感覺到。

沒有正确響應呢?

  • 如果Consumer接收了一個消息就還沒有發送ack就與RabbitMQ斷開了,RabbitMQ會認為這條消息沒有投遞成功會重新投遞到别的Consumer。
  • 如果Consumer本身邏輯有問題沒有發送ack的處理,RabbitMQ不會再向該Consumer發送消息。RabbitMQ會認為這個Consumer還沒有處理完上一條消息,沒有能力繼續接收新消息。

我們可以善加利用這一機制,如果需要處理過程是相當複雜的,應用程式可以延遲發送ack直到處理完成為止。這可以有效控制應用程式這邊的負載,不緻于被大量消息沖擊。

消息拒絕

由于要拒絕消息,是以ack響應消息還沒有發出,這裡拒絕消息可以有兩種選擇:

  • Consumer直接斷開RabbitMQ這樣RabbitMQ将把這條消息重新排隊,交由其它Consumer處理。這個方法在RabbitMQ各版本都支援,這樣做的壞處就是連接配接斷開增加了RabbitMQ的額外負擔,特别是consumer出現異常每條消息都無法正常處理的時候。
  • RabbitMQ 2.0.0可以使用 basic.reject 指令,收到該指令RabbitMQ會重新投遞到其它的Consumer。如果設定requeue為false,RabbitMQ會直接将消息從queue中移除。
  • 其實還有一種選擇就是直接忽略這條消息并發送ACK,當你明确知道這條消息是異常的不會有Consumer能處理,可以這樣做抛棄異常資料。

為什麼要發送basic.reject消息而不是ACK?RabbitMQ後面的版本可能會引入”dead letter”隊列,如果想利用dead letter做點文章就使用basic.reject并設定requeue為false。

消息持久化

RabbitMQ支援消息的持久化,也就是資料寫在磁盤上,為了資料安全考慮,大多數使用者都會選擇持久化。消息隊列持久化包括3個部分:

  1. Exchange持久化,在聲明時指定durable => 1
  2. Queue持久化,在聲明時指定durable => 1
  3. 消息持久化,在投遞時指定delivery_mode => 2(1是非持久化)

若Exchange和Queue都是持久化的,那麼它們之間的Binding也是持久化的;而Exchange和Queue兩者之間有一個持久化,一個非持久化,就不允許建立綁定。

Consumer從durable queue中取回一條消息之後并發回了ack消息,RabbitMQ就會将其标記,友善後續垃圾回收。如果一條持久化的消息沒有被consumer取走,RabbitMQ重新開機之後會自動重建exchange和queue(以及bingding關系),消息通過持久化日志重建再次進入對應的queues,exchanges。

RabbitMQ叢集

由于RabbitMQ是用erlang開發的,RabbitMQ完全依賴erlang的Cluster,因為erlang天生就是一門分布式語言,叢集非常友善,但其本身并不支援負載均衡。Erlang的叢集中各節點是經由過程一個magic cookie來實作的,這個cookie存放在 

$home/.erlang.cookie

中(像我的root使用者安裝的就是放在我的root/.erlang.cookie中),檔案是400的權限。是以必須保證各節點cookie内容一緻,不然節點之間就無法通信。

叢集方式

Rabbitmq叢集大概分為二種方式:

  1. 普通模式:預設的叢集模式。 

    對于Queue來說,消息實體隻存在于其中一個節點,A、B兩個節點僅有相同的中繼資料,即隊列結構,但隊列的中繼資料僅儲存有一份,即建立該隊列的rabbitmq節點(A節點),當A節點當機,你可以去其B節點檢視,./rabbitmqctl list_queues 發現該隊列已經丢失,但聲明的exchange還存在。

    當消息進入A節點的Queue中後,consumer從B節點拉取時,RabbitMQ會臨時在A、B間進行消息傳輸,把A中的消息實體取出并經過B發送給consumer,是以consumer應平均連接配接每一個節點,從中取消息。

    該模式存在一個問題就是當A節點故障後,B節點無法取到A節點中還未消費的消息實體。如果做了隊列持久化或消息持久化,那麼得等A節點恢複,然後才可被消費,并且在A節點恢複之前其它節點不能再建立A節點已經建立過的持久隊列;如果沒有持久化的話,消息就會失丢。

    這種模式更适合非持久化隊列,隻有該隊列是非持久的,用戶端才能重新連接配接到叢集裡的其他節點,并重新建立隊列。假如該隊列是持久化的,那麼唯一辦法是将故障節點恢複起來。

  2. 鏡像模式:把需要的隊列做成鏡像隊列,存在于多個節點。

    該模式解決了普通模式的問題,其實質不同之處在于,消息實體會主動在鏡像節點間同步,而不是在consumer取資料時臨時拉取。

    該模式帶來的副作用也很明顯,除了降低系統性能外,如果鏡像隊列數量過多,加之大量的消息進入,叢集内部的網絡帶寬将會被這種同步通訊大大消耗掉。

    是以在對可靠性要求較高的場合中适用,一個隊列想做成鏡像隊列,需要先設定policy,然後用戶端建立隊列的時候,rabbitmq叢集根據“隊列名稱”自動設定是普通叢集模式或鏡像隊列。具體如下:

    隊列通過政策來使能鏡像。政策能在任何時刻改變,rabbitmq隊列也近可能的将隊列随着政策變化而變化;非鏡像隊列和鏡像隊列之間是有差別的,前者缺乏額外的鏡像基礎設施,沒有任何slave,是以會運作得更快。

    為了使隊列稱為鏡像隊列,你将會建立一個政策來比對隊列,設定政策有兩個鍵“ha-mode和 ha-params(可選)”。ha-params根據ha-mode設定不同的值,下面表格說明這些key的選項。 

    RabbitMQ技術詳解(轉)

為什麼RabbitMQ不将隊列複制到叢集裡每個節點呢?這與它的叢集的設計本意相沖突,叢集的設計目的就是增加更多節點時,能線性的增加性能(CPU、記憶體)和容量(記憶體、磁盤)。理由如下:

  • Storage Space: If every cluster node had a full copy of every queue, adding nodes wouldn’t give you more storage capacity. For example, if one node could store 1GB of messages, adding two more nodes would simply give you two more copies of the same 1GB of messages.(存儲空間:如果每個叢集節點每個隊列的一個完整副本,增加節點需要更多的存儲容量。例如,如果一個節點可以存儲1 gb的消息,添加兩個節點需要兩份相同的1gb的消息)
  • Performance: Publishing messages would require replicating those messages to every cluster node. For durable messages that would require triggering disk activity on all nodes for every message. Your network and disk load would increase every time you added a node, keeping the performance of the cluster the same (or possibly worse).(性能:釋出消息需要将這些資訊複制到每個叢集節點。對持久消息,要求為每條消息觸發磁盤活動在所有節點上。每次添加一個節點都會帶來 網絡和磁盤的負載。)

當然RabbitMQ新版本叢集也支援隊列複制(有個選項可以配置)。比如在有五個節點的叢集裡,可以指定某個隊列的内容在2個節點上進行存儲,進而在性能與高可用性之間取得一個平衡(應該就是指鏡像模式)。

叢集節點

RabbitMQ的叢集節點包括記憶體節點、磁盤節點。顧名思義記憶體節點就是将所有資料放在記憶體,磁盤節點将資料放在磁盤。不過,如果在投遞消息時,打開了消息的持久化,那麼即使是記憶體節點,資料還是安全的放在磁盤。

一個rabbitmq集 群中可以共享 user,vhost,queue,exchange等,所有的資料和狀态都是必須在所有節點上複制的,一個例外是,那些目前隻屬于建立它的節點的消息隊列,盡管它們可見且可被所有節點讀取。rabbitmq節點可以動态的加入到叢集中,一個節點它可以加入到叢集中,也可以從叢集環叢集會進行一個基本的負載均衡。

叢集中有兩種節點:

  1. 記憶體節點:隻儲存狀态到記憶體(一個例外的情況是:持久的queue的持久内容将被儲存到disk)
  2. 磁盤節點:儲存狀态到記憶體和磁盤。

記憶體節點雖然不寫入磁盤,但是它執行比磁盤節點要好。叢集中,隻需要一個磁盤節點來儲存狀态 就足夠了如果叢集中隻有記憶體節點,那麼不能停止它們,否則所有的狀态,消息等都會丢失。

參考:

RabbitMQ消息隊列(一): Detailed Introduction 詳細介紹 

AMQP AND RABBITMQ 

消息隊列中間件的技術選型分析 

消息隊列軟體産品大比拼 

Message Queue Shootout! 

四種消息隊列性能測試源碼 

RabbitMQ與Erlang

RabbitMQ系列(一)AMQP協定

http://blog.csdn.net/butcher8/article/details/44274731(以上内容轉自此篇文章)