一、鏡像隊列
rabbitmq的集群創建后,默認消息只存在於隊列所在節點,當此節點故障后,消息就丟失了。
為了解決上述消息丟失的問題,引入RabbitMQ的鏡像隊列機制,將queue鏡像到cluster中其他的節點之上。
在該實現下,如果集群中的一個節點失效了,queue能自動地切換到鏡像中的另一個節點以保證服務的可用性。
鏡像隊列有如下特性:
- 每一個鏡像隊列都包含一個master和1個或多個slave
- 如果master失效了,最老的slave被選中為master
- 鏡像隊列不是負載均衡,鏡像隊列無法提升消息的傳輸效率
- 對exclusive隊列設置鏡像並不會有任何作用,因為exclusive隊列是連接獨占的,當連接斷開,隊列自動刪除
二、配置鏡像隊列
鏡像隊列是在普通集群搭建后,通過設置同步策略來實現的
rabbitmqctl set_policy [-p Vhost] Name Pattern Definition [Priority] -p Vhost: 可選參數,針對指定vhost下的queue進行設置 Name: policy的名稱 Pattern: queue的匹配模式(正則表達式) Definition:鏡像定義,包括三個部分ha-mode, ha-params, ha-sync-mode ha-mode:指明鏡像隊列的模式,有效值為 all/exactly/nodes all:表示在集群中所有的節點上進行鏡像 exactly:表示在指定個數的節點上進行鏡像,節點的個數由ha-params指定 nodes:表示在指定的節點上進行鏡像,節點名稱通過ha-params指定 ha-params:作為參數,為ha-mode的補充 ha-sync-mode:進行隊列中消息的同步方式,有效值為automatic和manual priority:可選參數,policy的優先級 rabbitmqctl set_policy ha-all "^" '{"ha-mode":"all"}' --apply-to all
三、鏡像隊列的結構
1、鏡像隊列基本上就是一個特殊的BackingQueue,它內部包裹了一個普通的BackingQueue做本地消息持久化處理,在此基礎上增加了將消息和ack復制到所有鏡像的功能。
2、所有對mirror_queue_master的操作,會通過組播的方式同步到各slave節點。
3、GM負責消息的組播,mirror_queue_slave負責回調處理,而master上的回調處理是由coordinator負責完成。
4、mirror_queue_slave中包含了普通的BackingQueue進行消息的存儲,master節點中BackingQueue包含在mirror_queue_master中由AMQQueue進行調用。
四、組播模塊GM
GM, Guarenteed Multicast. GM模塊實現的一種可靠的組播通訊協議,該協議能夠保證組播消息的原子性,即保證組中活着的節點要么都收到消息要么都收不到。
在master節點和slave節點上的gm形成一個組,不同的鏡像隊列形成不同的group。
它的實現大致如下:
將所有的節點形成一個循環鏈表,每個節點都會監控位於自己左右兩邊的節點
1、當有節點新增時,相鄰的節點保證當前廣播的消息會復制到新的節點上
2、當有節點失效時,相鄰的節點會接管保證本次廣播的消息會復制到所有的節點
五、新增節點的消息同步
一個queue正在同步,所有對於其他的queues的操作將會被阻塞,不建議在生產的active隊列(有生產消費消息)中操作。
一個節點可以在任何時候加入集群之中。
根據queue的配置,當新節點加入進來的時候,這個queue有可能在這個新的節點上添加一個鏡像,此時這個鏡像是空的。
什么時候進行消息同步呢?這個涉及到ha-sync-mode這個的參數。
1、ha-sync-mode=automatic,新加入節點時會默認同步已知的鏡像隊列
2、ha-sync-mode=manual(默認值)
鏡像隊列中的消息不會主動同步到新節點,除非顯式調用同步命令。當調用同步命令后,隊列開始阻塞,無法對其進行操作,直到同步完畢
rabbitmqctl list_queues name slave_pids synchronised_slave_pids 查看隊列同步情況
rabbitmqctl sync_queue name 同步指定隊列
rabbitmqctl cancel_sync_queue name 取消同步
在此狀態下,可選擇另外一種方式,避免影響。新加入的鏡像可以收到生產者新發送過來的消息,其內容與其他鏡像的尾部保持一致。隨着queue中的消息被逐漸的消費,新加入的鏡像中“錯失”的消息逐漸減少,直到與其他鏡像保持一致。
六、隊列或節點故障
1、master和全部或部分slave處於同步狀態
一般情況最老的slave被選中為master
2、所有slave都處於未同步狀態
1)ha-promote-on-shutdown=when-synced(默認)
master因為主動的原因停掉,比如是通過rabbitmqctl stop命令停止或者優雅關閉OS,那么slave不會接管master,也就是此時鏡像隊列不可用
master因為被動原因停掉,比如VM或者OS crash了,那么slave會接管master
2)ha-promote-on-shutdown=always
不論master因為何種原因停止,slave都會接管master,優先保證可用性。