rabbitmq每個節點記錄四類信息:交換機、隊列、綁定、vhost元數據。
集羣中的信息存儲
在rabbitmq2.6.0之前沒有鏡像隊列,數據存儲情況爲:
隊列所屬節點保存隊列全部信息(元數據、狀態、內容),其他節點擁有隊列元數據;所有節點保存exchange、bundling信息。好處有兩點:
1.節約存儲空間,每個節點都有相同信息的拷貝,意味着磁盤空間成倍佔用;
2.提升性能,數據在節點間同步佔用網絡資源,如果是持久化狀態,又會有大量I/O;
正常情況的工作原理:
集羣中有三個節點:rabbit、hare、hare1,隊列聲明在hare節點,向rabbit節點發消息,消息會轉發到hare節點,消費者連接hare1節點,則從hare節點讀取數據。
異常情況1(發送過程中故障):
向rabbit節點發送5條消息,第一條發送成功後,關掉hare節點
2017-11-16 12:05:07,015 [http-bio-8080-exec-1]
[org.springframework.amqp.rabbit.core.RabbitTemplate]-[DEBUG] Publishing message (Body:'< publish
message 內容爲:[ Thu Nov 16 12:05:07 CST 2017 ]>' MessageProperties [headers={},
contentType=text/plain, contentEncoding=UTF-8, contentLength=62, deliveryMode=PERSISTENT, priority=0, deliveryTag=0])on exchange [AMC_TMP_EXCHANGE], routingKey = [cluster.send]
控制檯顯示正常發送,實際上後面4條消息已經丟失
localhost:sbin zcjlq$ ./rabbitmqctl -n hare stop_app
Stopping rabbit application on node hare@localhost
localhost:sbin zcjlq$ ./rabbitmqctl -n rabbit -p zcjlq list_queues
Listing queues
AMC_TMP_QUEUE
hare節點重啓,只有第一條消息
localhost:sbin zcjlq$ ./rabbitmqctl -n hare start_app
Starting node hare@localhost
localhost:sbin zcjlq$ ./rabbitmqctl -n rabbit -p zcjlq list_queues
Listing queues
AMC_TMP_QUEUE 1
拓展:
如果使用publisher confirm機制,在回調函數RabbitTemplate.ConfirmCallback,你將拿到5個ack,RabbitTemplate.ReturnCallback不會被回調。
異常情況2(發送完畢故障):
假如我們連上任意節點,發送4條消息,先不消費,各個節點都能查到消息。
下面停掉隊列所屬節點hare
localhost:sbin zcjlq$ ./rabbitmqctl -n rabbit -p zcjlq list_queues
Listing queues
AMC_TMP_QUEUE 4
localhost:sbin zcjlq$ ./rabbitmqctl -n hare1 -p zcjlq list_queues
Listing queues
AMC_TMP_QUEUE 4
localhost:sbin zcjlq$ ./rabbitmqctl -n hare stop_app
Stopping rabbit application on node hare@localhost
localhost:sbin zcjlq$ ./rabbitmqctl -n hare1 -p zcjlq list_queues
Listing queues
AMC_TMP_QUEUE
localhost:sbin zcjlq$ ./rabbitmqctl -n rabbit -p zcjlq list_queues
Listing queues
AMC_TMP_QUEUE
localhost:sbin zcjlq$ ./rabbitmqctl -n hare start_app
Starting node hare@localhost
localhost:sbin zcjlq$ ./rabbitmqctl -n rabbit -p zcjlq list_queues
Listing queues
AMC_TMP_QUEUE 4
localhost:sbin zcjlq$ ./rabbitmqctl -n hare1 -p zcjlq list_queues
Listing queues
AMC_TMP_QUEUE 4
我們發現:停用hare節點後,在另外兩個節點查不到消息,hare節點重啓後,三個節點都能查到消息。
說明:本測試在單機上啓動三個節點(單機集羣搭建見後續文章)
rabbitmqctl -n參數指定節點名稱,-p指定vhost名稱,start_app啓動節點,stop_app關閉節點,
list_queues查看隊列列表和待消費消息。
異常情況3(故障期間重新聲明隊列):
在恢復hare節點前,我們嘗試通過其他節點重新創建隊列。出現以下錯誤
Caused by: com.rabbitmq.client.ShutdownSignalException: channel error; protocol method:
#method<channel.close>(reply-code=404, reply-text=NOT_FOUND - home node 'hare@localhost'
of durable queue 'AMC_TMP_QUEUE' in vhost 'zcjlq' is down or inaccessible, class-id=50, method-id=10)
節點類型
集羣中的節點有兩個類型:磁盤節點、內存節點。內存節點(ram)將所有的隊列、交換器、綁定、用戶、權限、vhost的元數據定義都僅存儲於內存中。磁盤節點(disc)將元數據存儲在磁盤中。
是磁盤節點還是內存節點?
在集羣中聲明隊列、交換器、綁定的時候,其他節點會得到元數據的同步,如果集羣中全都是磁盤節點,那麼你需要等到所有的節點都磁盤I/O後才完成工作,內存節點將會更快。
rabbitmq要求集羣中至少有一個磁盤節點。磁盤節點離開集羣時,集羣還可以進行部分工作,創建隊列、創建交換機、創建綁定、添加用戶、更改權限、添加或刪除集羣節點將不能使用。原理的磁盤節點重啓後,集羣可以正常工作。我們想要更安全一點:原磁盤節點重啓前,爲讓集羣正常工作,這時候可以考慮設置兩個集羣節點,當其中一個磁盤節點離開時,它會將該變更通知到至少一個磁盤節點。