更新時間:2022-07-22 09:44:59 來源:動力節(jié)點 瀏覽2396次
在Java教程中,大家會學(xué)習(xí)RabbitMQ,那么,RabbitMQ集群原理是什么?動力節(jié)點小編來帶大家一起了解一下。
RabbitMQ 本身是基于 Erlang 編寫的,Erlang 語言本質(zhì)上是分布式的(通過同步 Erlang 集群各個節(jié)點的 erlang.cookie 來實現(xiàn))。因此,RabbitMQ 自然支持集群。集群是保證可靠性的一種方式,同時可以橫向擴展,達(dá)到提高消息吞吐量的目的。
下圖顯示了一個集群示例:

上面圖中采用三個節(jié)點組成了一個RabbitMQ的集群,Exchange A(交換器)的元數(shù)據(jù)信息在所有節(jié)點上是一致的,而Queue(存放消息的隊列)的完整數(shù)據(jù)則只會存在于它所創(chuàng)建的那個節(jié)點上。,其他節(jié)點只知道這個queue的metadata信息和一個指向queue的owner node的指針。
RabbitMQ集群元數(shù)據(jù)的同步
RabbitMQ集群會始終同步四種類型的內(nèi)部元數(shù)據(jù):
a. 隊列元數(shù)據(jù):隊列名稱和它的屬性
b. 交換器元數(shù)據(jù):交換器名稱、類型和屬性
c. 綁定元數(shù)據(jù):一張簡單的表格展示了如何將消息路由到隊列
d. vhost元數(shù)據(jù):為vhost內(nèi)的隊列、交換器和綁定提供命名空間和安全屬性
因此,當(dāng)用戶訪問其中任何一個RabbitMQ節(jié)點時,通過rabbitmqctl查詢到的queue/user/exchange/vhost等信息都是相同的。
為什么 RabbitMQ 集群只使用元數(shù)據(jù)同步?
(1)存儲空間。如果每個集群節(jié)點都有所有Queue的完整數(shù)據(jù)副本,那么每個節(jié)點的存儲空間會非常大,集群的消息積壓能力會很弱(消息積壓能力無法通過擴容來提升)集群節(jié)點);
(2)性能。消息的發(fā)布者需要將消息復(fù)制到每個集群節(jié)點。對于持久化消息,網(wǎng)絡(luò)和磁盤同步復(fù)制的開銷會顯著增加。
RabbitMQ集群工作原理圖如下:

客戶端直接連接隊列所在節(jié)點
如果消息生產(chǎn)者或消息消費者通過amqp-client的客戶端連接到節(jié)點1發(fā)布或訂閱消息,那么此時集群中的消息發(fā)送和接收只與節(jié)點1相關(guān)。
客戶端連接到非隊列數(shù)據(jù)所在節(jié)點
如果消息生產(chǎn)者連接到節(jié)點2或節(jié)點3,隊列1的完整數(shù)據(jù)不在這兩個節(jié)點上,那么這兩個節(jié)點在發(fā)送消息的過程中主要起到路由轉(zhuǎn)發(fā)的作用,根據(jù)這兩個節(jié)點上的元數(shù)據(jù)被轉(zhuǎn)發(fā)到節(jié)點1,最終發(fā)送的消息仍然會存儲在節(jié)點1的隊列1中。同樣,如果消息消費者連接的節(jié)點2或節(jié)點3,這兩個節(jié)點也會充當(dāng)路由節(jié)點轉(zhuǎn)發(fā)消息,消息會從節(jié)點1的隊列1中拉取消費。
集群節(jié)點類型
磁盤節(jié)點:在磁盤上存儲配置信息和元信息(單節(jié)點系統(tǒng)必須是磁盤節(jié)點,否則每次重啟RabbitMQ都會丟失所有系統(tǒng)配置信息)。
內(nèi)存節(jié)點:在內(nèi)存中存儲配置信息和元信息。性能優(yōu)于磁盤節(jié)點。
RabbitMQ 要求集群中至少有一個磁盤節(jié)點。當(dāng)節(jié)點加入和離開集群時,必須通知磁盤節(jié)點(如果集群中唯一的磁盤節(jié)點崩潰,則不能創(chuàng)建隊列、創(chuàng)建交換機、創(chuàng)建綁定、添加用戶、更改權(quán)限、添加和刪除集群節(jié)點)。簡而言之,如果唯一磁盤的磁盤節(jié)點崩潰,集群可以繼續(xù)運行,但什么都不能改變。因此,建議在集群中設(shè)置兩個磁盤節(jié)點,只要一個可用,就可以正常運行。
概括
普通集群模式不保證隊列的高可用。雖然交換機和綁定可以復(fù)制到集群中的任何節(jié)點,但不會復(fù)制隊列的內(nèi)容。這種模式雖然解決了一個項目組的節(jié)點壓力,但是隊列節(jié)點的宕機直接導(dǎo)致隊列不可用,只能等待重啟。因此,如果要在隊列節(jié)點宕機或故障時正常工作,必須將隊列的內(nèi)容復(fù)制到集群中的各個節(jié)點,并且必須創(chuàng)建鏡像隊列。
鏡像隊列是在普通集群模式的基礎(chǔ)上,再加入一些策略。所以必須先配置普通集群,然后才能設(shè)置鏡像隊列。鏡像隊列存在于多個節(jié)點上。要實現(xiàn)鏡像模式,需要先搭建一個普通的集群模式,然后在這個模式的基礎(chǔ)上配置鏡像模式,實現(xiàn)高可用。
鏡像隊列的結(jié)構(gòu)

鏡像隊列基本上就是一個特殊的BackingQueue,它包裝了一個普通的BackingQueue,用于本地消息持久化處理,并在此基礎(chǔ)上增加了復(fù)制消息和確認(rèn)所有鏡像的功能。mirror_queue_master 上的所有操作都會通過可靠的多播 GM 同步到各個從節(jié)點。GM負(fù)責(zé)消息的廣播,mirror_queue_slave負(fù)責(zé)回調(diào)處理,master上的回調(diào)處理由coordinator完成。mirror_queue_slave包含了普通的BackingQueue用于消息存儲,主節(jié)點的BackingQueue包含在mirror_queue_master中,被AMQQueue調(diào)用。
消息的發(fā)布(Basic.Publish除外)和消費都是通過主節(jié)點完成的。主節(jié)點在處理消息的同時,通過 GM 將消息的處理動作廣播給所有從節(jié)點。slave節(jié)點的GM收到消息后,通過回調(diào)將消息交還給mirror_queue_slave進行實際處理。
對于 Basic.Publish,消息同時發(fā)送到主服務(wù)器和所有從服務(wù)器。如果此時master宕機了,消息也會發(fā)給slave,這樣slave提升為master時消息就不會丟失。
GM(保證組播)
GM模塊實現(xiàn)的一種可靠的組播通信協(xié)議,可以保證組播消息的原子性,即保證組內(nèi)所有存活的節(jié)點都收到或不收到消息。
其實現(xiàn)大致如下:
所有節(jié)點組成一個循環(huán)鏈表,每個節(jié)點都會監(jiān)控自己左右兩邊的節(jié)點。當(dāng)添加一個節(jié)點時,相鄰節(jié)點保證將當(dāng)前廣播消息復(fù)制到新節(jié)點;當(dāng)某個節(jié)點發(fā)生故障時,相鄰節(jié)點將接管,以確保將廣播消息復(fù)制到所有節(jié)點。主節(jié)點和從節(jié)點上的這些gm組成一個組,組的信息(gm_group)會記錄在mnesia中。不同的鏡像隊列形成不同的組。消息從主節(jié)點發(fā)送到gm后,沿著鏈表依次傳遞給所有節(jié)點。由于所有節(jié)點形成一個循環(huán)鏈表,主節(jié)點對應(yīng)的gm最終會收到自己發(fā)送的消息。此時,主節(jié)點將知道消息已發(fā)送。復(fù)制到所有從節(jié)點。
新節(jié)點
新節(jié)點的加入流程如下圖所示:

每當(dāng)節(jié)點加入或重新加入(例如從網(wǎng)絡(luò)分區(qū)恢復(fù))鏡像隊列時,之前保存的隊列內(nèi)容將被清除。
在現(xiàn)有鏡像隊列中添加新節(jié)點時,默認(rèn)ha-sync-mode=manual,除非顯式調(diào)用同步命令,否則鏡像隊列中的消息不會主動同步到新節(jié)點。當(dāng)調(diào)用同步命令時,隊列開始阻塞,直到同步完成才能操作。
當(dāng) ha-sync-mode=automatic 時,添加新節(jié)點時默認(rèn)同步已知鏡像隊列。由于同步過程的限制,不建議在生產(chǎn)消費隊列中操作。
節(jié)點故障
如果一個從站發(fā)生故障,系統(tǒng)除了記錄之外幾乎什么都不做。master還是master,client不需要做任何動作,也不需要通知slave的失敗。如果主站失敗,則必須選擇其中一個從站作為主站。被選為新master的slave通常是最老的,因為最老的slave和之前的master之間的同步狀態(tài)應(yīng)該是最好的。但是需要注意的是,如果沒有slave與master完全同步,那么之前master中未同步的消息就會丟失。
概括
鏡像節(jié)點在集群中的其他節(jié)點上擁有從屬隊列的副本。一旦主節(jié)點不可用,最舊的從隊列將被選為新的主隊列。但是鏡像隊列不能用作負(fù)載均衡器,因為每個操作都必須在所有節(jié)點上完成。這種模式的副作用也很明顯。除了降低系統(tǒng)性能外,如果鏡像隊列過多,大量消息進入,集群內(nèi)部的網(wǎng)絡(luò)帶寬也會被這種同步通信大大消耗。因此,適用于對可靠性要求較高的場合。
以上就是關(guān)于“帶你一起了解RabbitMQ集群原理”的介紹,大家如果對此比較感興趣,想了解更多相關(guān)知識,可以關(guān)注一下動力節(jié)點的RabbitMQ教程,里面有更豐富的知識等著大家去學(xué)習(xí),希望對大家能夠有所幫助。