RabbitMQ集羣是按照低延遲環境設計的,千萬不要跨越WAN或者互聯網來搭建RabbitMQ集羣。若是必定要在高延遲環境下使用RabbitMQ集羣,能夠參考使用Shovel和Federation工具。安全
RabbitMQ社區中的傳統觀念要求集羣中節點數量的上限在32至64個,由於每向集羣添加一個節點,就添加了同步的複雜性。集羣中的每一個節點必須知道其餘節點的信息,這種非線性的複雜度會拖慢消息投遞和集羣管理。bash
RabbitMQ集羣設計目的有兩個:網絡
當一個RabbitMQ集羣節點崩潰時,該節點上隊列的消息也會消失。這事由於RabbitMQ默認不會將隊列的內容複製到整個集羣上。若是不進行特別的配置,這些消息僅存在於隊列所屬的那個節點上。架構
RabbitMQ會始終記錄如下四種類型的內部元數據:工具
當你引入集羣時,RabbitMQ須要追蹤新的元數據類型 —— 集羣節點位置,以及節點與已記錄的其餘類型元數據的關係。集羣也提供了將元數據存儲到磁盤或內存中的選項。性能
不是每個節點都有全部隊列的徹底拷貝。 在集羣中建立隊列的話,集羣只會在單個節點(而不是全部節點)上建立完整的隊列信息。 結果是,只有隊列的全部者節點,知道有關隊列的全部信息。 其餘非隊列全部者的節點們,只知道隊列的元數據和指向隊列存在的那個節點的指針。 所以,當集羣節點崩潰時,該節點的隊列和關聯的綁定就都消失了。 附加在那些隊列上的消費者丟失了訂閱。 而且任何匹配該隊列綁定信息的新消息也丟失了。
若是消費者要消費的隊列的所在節點故障了,而該隊列是持久化的,那麼想要繼續消費,惟一的辦法就是恢復故障節點。當失敗節點恢復後加入集羣,該節點上的隊列消息不會丟失。spa
嘗試在持久化隊列節點故障後,從新聲明隊列,會獲得一個404 NOT_FOUND錯誤。但若是隊列不是持久化的,那麼從新聲明就會成功。插件
RabbitMQ設計上不將隊列內容和狀態複製到全部的節點上,主要有兩個緣由:設計
存儲空間 —— 若是一個節點能夠存儲1GB的消息,那麼在多個節點之間複製消息則會浪費多個G的空間;指針
性能因素 —— 消息的發佈須要將消息複製到每個節點,對於持久化消息來講,每次都會觸發磁盤活動,每次新增節點,網絡和磁盤負載都會增長;
另外,在向隊列發送消息時,只有隊列的全部節點,纔會收到磁盤操做的影響。其餘非全部節點,只須要將接收到的消息傳遞給全部者節點便可。
所以,往Rabbit集羣中添加更多的節點,就意味着將擁有更多的節點來傳播消息,多個節點會帶來性能的提高。
交換器,本質上就是一個名稱和隊列綁定的列表。
當你將消息發佈到交換器時,其實是由鏈接的信道,根據消息上的路由鍵,去交換器綁定列表中進行比較,而後路由消息到隊列中。
因爲交換器只不過是一張表,所以將這張表在集羣中複製很簡單,當建立一個新的交換器時,RabbitMQ所要作的是將交換器添加到集羣中的全部節點上。
集羣的消息可靠性與單點模式基本一致。AMQP的Basic.Publish命令不會返回消息的狀態。這意味着當信道節點崩潰時,信道可能仍然在路由消息,解決方案是使用事務,或發佈確認模式。
RabbitMQ的集羣大體上可分爲3類:
當建立集羣時,至少保證一個磁盤節點和若干個內存節點。不管哪一種節點,都不會影響消息持久化。
當有多個磁盤節點時,就能在發生硬件故障時更加遊刃有餘。
若存在多個磁盤節點,在發生故障恢復時可能會出現狀態不一致的狀況,這種時候,可關閉集羣並按照順序從新啓動節點。
統計節點,只能和磁盤節點搭配使用。它負責收集集羣中每一個節點的所有統計數據和狀態數據。在任什麼時候候,一個集羣只能有一個統計節點。
在擁有兩個磁盤節點的集羣中,若是主節點發生故障,統計節點將指派給備用的磁盤節點。
若是隻有一個磁盤節點,當這個節點發生故障後,集羣仍是能夠繼續路由消息,可是不能作如下操做:
最好是設置一個以上的磁盤節點,在某個磁盤節點故障時,還有備用的磁盤節點可用。
當內存節點添加到集羣或從新加入到集羣時,他們會鏈接到預先配置的磁盤節點,下載集羣元數據。當添加內存節點時,確保告知該內存節點全部的磁盤節點。
集羣的升級是半自動化的,在沒有準備的狀況下解壓新版本的RabbitMQ覆蓋舊版本,會抹去集羣上全部配置和數據。若是要保留這些,須要進行一些操做。
首先,經過Management插件備份配置;
而後,關閉全部生產者並等待全部消費者消費完隊列中全部的消息(使用rabbitmqctl觀察隊列狀態);
接着,關閉節點並解壓新版本的RabbitMQ;
隨後,選擇其中一個磁盤節點做爲升級節點,當它啓動時,該節點會將持久化的集羣數據升級到新版本,而後在啓動其餘的磁盤節點;
最後,啓動內存節點,這樣就會讓集羣中運行新版本的RabbitMQ了,並且元數據都會保留;
在RabbitMQ2.6版本後,RabbitMQ團隊給集羣帶來了內建的雙冗餘選項:鏡像隊列。
想普通隊列那樣,鏡像隊列的主拷貝僅存在於一個節點(主隊列,Master)上,但與普通隊列不一樣的是,鏡像節點在集羣中的其餘節點上擁有從隊列(slave)拷貝。一旦隊列主節點不可用,最老的從隊列將被選舉爲主隊列。
在定義隊列時,加入參數:
x-ha-policy = all
這意味着隊列被鏡像到集羣中的全部節點上。若是在該隊列聲明以後,集羣又新增了節點,那麼該節點也會自動託管一份隊列的從拷貝。
消息發送到隊列時,若是隊列是鏡像隊列,那麼也要將消息投遞到鏡像隊列的從拷貝。
想確保消息沒有丟失的話,同樣可使用發佈確認模式,不一樣的是,RabbitMQ會在全部隊列安全的接收了消息後在通知你。
這裏須要有從發佈者和消費者兩方面說一下異常狀況:
注意:若是消費者鏈接在從拷貝,當主拷貝發生變化時,RabbitMQ會發送給客戶端一個Consumer Cancellation的通知,告知客戶端發生了變化。若是你的客戶端不支持這個通知處理的話,你的程序會空跑,覺得隊列中沒有消息能夠消費了。 若是你的客戶端不支持這個消費者取消通知處理,那麼應該避免使用鏡像隊列!!!