參考資料:
https://www.cnblogs.com/xishuai/p/rabbitmq-cluster.html
http://www.ywnds.com/?p=4741
https://blog.csdn.net/zhu_tianwei/article/details/40930305
對(duì)異常情況解釋的比較多
為什么需要集群
- 擺脫單機(jī)資源上的限制,提供更大的吞吐量
- 提供更加穩(wěn)定的更高可用的服務(wù)
集群中節(jié)點(diǎn)之間需要同步的信息rabbitmq的元數(shù)據(jù)
a. 隊(duì)列元數(shù)據(jù):隊(duì)列名稱和它的屬性;
b. 交換器元數(shù)據(jù):交換器名稱、類型和屬性;
c. 綁定元數(shù)據(jù):一張簡(jiǎn)單的表格展示了如何將消息路由到隊(duì)列;
d. vhost元數(shù)據(jù):為vhost內(nèi)的隊(duì)列、交換器和綁定提供命名空間和安全屬性;
e. 元數(shù)據(jù)信息需要保存的磁盤中,所以每個(gè)集群中至少需要一個(gè)disk節(jié)點(diǎn)
因此,當(dāng)用戶訪問其中任何一個(gè)RabbitMQ節(jié)點(diǎn)時(shí),通過rabbitmqctl查詢到的queue/user/exchange/vhost等信息都是相同的。

rabbitmq 的集群模式
集群內(nèi)節(jié)點(diǎn)的類型
磁盤節(jié)點(diǎn)
保存數(shù)據(jù)到磁盤和內(nèi)存中,如果集群中群都是內(nèi)存節(jié)點(diǎn),那就不能停止他們,否則元數(shù)據(jù)就會(huì)丟。
RabbitMQ只要求集群中至少有一個(gè)磁盤節(jié)點(diǎn),如果只有一個(gè)磁盤節(jié)點(diǎn),剛好又崩潰了,集群可以繼續(xù)路由消息,但不能創(chuàng)建隊(duì)列、交換器、綁定、添加用戶、更改權(quán)限等操作。所以,
建議設(shè)置兩個(gè)磁盤節(jié)點(diǎn),當(dāng)內(nèi)存節(jié)點(diǎn)重啟后,會(huì)連接到預(yù)先配置的磁盤節(jié)點(diǎn),下載當(dāng)前集群元數(shù)據(jù)拷貝,所以要將所有磁盤節(jié)點(diǎn)告訴內(nèi)存節(jié)點(diǎn)。
內(nèi)存節(jié)點(diǎn)
數(shù)據(jù)只保存到內(nèi)存中,除非遇到
- publish消息的時(shí)候指定需要持久化
- 內(nèi)存吃緊的時(shí)候,會(huì)把部分消息持久化到磁盤
內(nèi)存節(jié)點(diǎn)的特點(diǎn)就是執(zhí)行效率高
普通模式
不是每個(gè)節(jié)點(diǎn)都有所有隊(duì)列的完全拷貝,如果在集群中創(chuàng)建隊(duì)列,只會(huì)在單個(gè)節(jié)點(diǎn)上創(chuàng)建完整的隊(duì)列信息(元數(shù)據(jù)、狀態(tài)、內(nèi)容),所有其他節(jié)點(diǎn)只知道隊(duì)列的元數(shù)據(jù)和指向該隊(duì)列的節(jié)點(diǎn)指針。
既然一個(gè)隊(duì)列的數(shù)據(jù)只存在一個(gè)節(jié)點(diǎn)上,那么在連接集群內(nèi)其他節(jié)點(diǎn)的時(shí)候,是如何進(jìn)行發(fā)布消息和消費(fèi)消息的呢?
如果消息生產(chǎn)者所連接的是節(jié)點(diǎn)2或者節(jié)點(diǎn)3,此時(shí)隊(duì)列1的完整數(shù)據(jù)不在該兩個(gè)節(jié)點(diǎn)上,那么在發(fā)送消息過程中這兩個(gè)節(jié)點(diǎn)主要起了一個(gè)路由轉(zhuǎn)發(fā)作用,根據(jù)這兩個(gè)節(jié)點(diǎn)上的元數(shù)據(jù)(也就是上文提到的:指向queue的owner node的指針)轉(zhuǎn)發(fā)至節(jié)點(diǎn)1上,最終發(fā)送的消息還是會(huì)存儲(chǔ)至節(jié)點(diǎn)1的隊(duì)列1上。
同樣,如果消息消費(fèi)者所連接的節(jié)點(diǎn)2或者節(jié)點(diǎn)3,那這兩個(gè)節(jié)點(diǎn)也會(huì)作為路由節(jié)點(diǎn)起到轉(zhuǎn)發(fā)作用,將會(huì)從節(jié)點(diǎn)1的隊(duì)列1中拉取消息進(jìn)行消費(fèi)。
如果節(jié)點(diǎn)崩潰了,附加在隊(duì)列上的消費(fèi)者也就無法接收新的消息了。可以讓消費(fèi)者重連到集群并重新創(chuàng)建隊(duì)列,這種做法僅當(dāng)隊(duì)列沒設(shè)置持久化時(shí)才可行,如果做了隊(duì)列持久化或消息持久化,必須等到對(duì)應(yīng)的節(jié)點(diǎn)恢復(fù)了才能被消費(fèi),這是為了確保當(dāng)失敗的節(jié)點(diǎn)恢復(fù)后加入集群,節(jié)點(diǎn)上的隊(duì)列消息不會(huì)丟失。
為什么不將隊(duì)列內(nèi)容和狀態(tài)復(fù)制到所有節(jié)點(diǎn):
- 存儲(chǔ)空間,如果每個(gè)集群節(jié)點(diǎn)都擁有所有隊(duì)列的完全拷貝,添加新節(jié)點(diǎn)不會(huì)帶來更多存儲(chǔ)空間;
- 性能,消息的發(fā)布者需要將消息復(fù)制到每一個(gè)集群節(jié)點(diǎn),對(duì)于持久化消息,網(wǎng)絡(luò)和磁盤復(fù)制都會(huì)增加。
優(yōu)點(diǎn):
- 使用集群能很好的實(shí)現(xiàn)服務(wù)能力的水平拓展
缺點(diǎn):
- 因?yàn)閱蝹€(gè)隊(duì)列只維持在單個(gè)節(jié)點(diǎn)上,也很難認(rèn)為是高可用
- 如果是不持久化的消息和隊(duì)列,單機(jī)宕機(jī)后消息會(huì)丟失
鏡像模式 把需要的隊(duì)列做成鏡像隊(duì)列,存在于多個(gè)節(jié)點(diǎn),屬于RabbitMQ的HA方案
根據(jù)策略可以為節(jié)點(diǎn)定義鏡像節(jié)點(diǎn),鏡像節(jié)點(diǎn)之間可以實(shí)現(xiàn)隊(duì)列中消息實(shí)體的同步。
對(duì)于發(fā)送方確認(rèn)消息,Rabbit會(huì)在所有隊(duì)列和隊(duì)列的從拷貝安全地接收到消息時(shí),才會(huì)通知發(fā)送方。

優(yōu)點(diǎn):
- 因?yàn)槟軐?duì)節(jié)點(diǎn)維護(hù)的隊(duì)列中的消息實(shí)體做了同步,可以保證
缺點(diǎn):
- 因?yàn)橐M(jìn)行消息實(shí)體的復(fù)制,所以勢(shì)必會(huì)影響系統(tǒng)的性能
- 網(wǎng)絡(luò)通信也會(huì)加大,如果消息量比較大話