【rabbitmq】RabbitMQ 集羣與網絡分區

網絡分區(network partitions)

官網-網絡分區html

網絡設備故障致使的網絡分裂。好比,存在A\B\C\D\E五個節點,A\B處於同一子網,B\C\D處於另一子網,中間經過交換機相連。若兩個子網間的交換機故障了即發生了網絡分區,A\B和C\D\E便不能通信。
某些系統是partition-tolerant的,也即,即便發生了網絡分區系統分裂爲了多個子系統,整個系統仍能正常工做。node

RabbitMQ cluster不能很好地處理Network Partition。RabbitMQ將queue、exchange、bindings等信息存儲在Erlang的分佈式數據庫Mnesia中。因此出現Network partition時RabbitMQ的衆多行爲與Mnesia的行爲密切相關。數據庫

Network Partition的斷定

若某一node在一段時間內(取決於net_ticktime的設置)不能與另外一node取得聯繫,則Mnesia認爲未能與之取得聯繫的node宕掉了。若兩個node彼此恢復聯繫了,但都曾覺得對方宕掉了,則Manesia判定發生過Network partition。數組

發生Network Partition後RabbitMQ的行爲

若發生了network partition,cluster中的雙方(或多方)將獨立存在,每一方都將認爲其餘方已經崩潰了。Queues、bindings、exchanges能夠各自獨立的建立、刪除。對於Mirrored queues,處於不一樣network partition的每一方都會擁有各自的master,且各自獨立的讀寫。(也可能發生其餘詭異的行爲)。若network partition恢復了,cluster的狀態並不能自動恢復到network partition發生前的狀態,直至採起措施進行修復。安全

網絡分區的可能緣由

只要cluster中的不一樣node自身沒有失效但之間的通訊發生了中斷均可認爲是發生了Partitions。好比,整個OS的掛起會致使其中的cluster nodes的掛起,但這些nodes卻不認爲自身失效或中止了,而cluster中的其它nodes不能與之取得聯繫,會認爲這些nodes down掉了。舉個例子:若cluster中的一個node運行在筆記本電腦上,合上電腦屏幕就有可能致使node掛起。另外,若cluster中的node運行在虛擬機中,則管理程序可能致使虛擬機掛起,從而使node掛起。網絡

  • 狀況1:集羣中的nodes,都沒有故障下線,可是node之間通訊中斷;
  • 狀況2:暫停/恢復運行中node的操做系統也可能致使network分區:暫停的node不認爲它已經fail或stop,但集羣中的其餘nodes認爲它已經fail了。
  • 狀況3:發生這種狀況的最多見緣由是:虛擬機已被虛擬機管理程序掛起;
  • 狀況4:虛擬機的遷移(rabbitmq運行在該vm上),也可能會致使vm被掛起,從而發生網絡分區
  • 狀況總結:就是某個node因各類緣由,和集羣中的其餘節點發生通訊中斷,雖然該節點不認爲本身下線,可是集羣中的其餘節點已經認爲該節點下線了。

檢查網絡分區

能夠經過rabbitmqctl cluster_status來查看是否發生了網絡分區
正常的狀態信息:分佈式

[root@rmq-node3 ~]# rabbitmqctl cluster_status
Cluster status of node 'rabbit@rmq-node3'
[{nodes,[{disc,['rabbit@rmq-node2','rabbit@rmq-node1']},
         {ram,['rabbit@rmq-node3']}]},
 {running_nodes,['rabbit@rmq-node1','rabbit@rmq-node2','rabbit@rmq-node3']},
 {cluster_name,<<"rabbit@rmq-node1">>},
 {partitions,[]},                    #注意,這裏爲空數組,代表沒有發生網絡分區
 {alarms,[{'rabbit@rmq-node1',[]},
          {'rabbit@rmq-node2',[]},
          {'rabbit@rmq-node3',[]}]}]

發生網絡分區的狀態信息:this

[root@rmq-node3 ~]# rabbitmqctl cluster_status
Cluster status of node 'rabbit@rmq-node3'
[{nodes,[{disc,['rabbit@rmq-node2','rabbit@rmq-node1']},
         {ram,['rabbit@rmq-node3']}]},
 {running_nodes,['rabbit@rmq-node1','rabbit@rmq-node2','rabbit@rmq-node3']},
 {cluster_name,<<"rabbit@rmq-node1">>},
 {partitions,[{'rabbit@rmq-node1',['rabbit@rmq-node2','rabbit@rmq-node3']}]},  #這裏是發生了network partitions
 {alarms,[{'rabbit@rmq-node1',[]},
          {'rabbit@rmq-node2',[]},
          {'rabbit@rmq-node3',[]}]}]

當發生網絡分區時,會提示以下信息:操作系統

While running in this partitioned state, changes (such as queue or exchange declaration and binding) which take place in one partition will not be visible to other partition(s). Other behaviour is not guaranteed.  
==>代表 元數據的改變,不會在節點之間同步

也能夠經過查看日誌找到該問題:日誌

vi /var/log/rabbitmq/rabbit-xxx.log

=ERROR REPORT==== 9-Aug-2018::20:15:45 ===
Mnesia('rabbit@rmq-node2'): ** ERROR ** mnesia_event got {inconsistent_database, starting_partitioned_network, 'rabbit@rmq-node1'}

網絡分區的恢復

首先選一個最信任的partition,Mnesia使用該partition中的狀態,其餘partitions中發生的變化都將丟失。
中止其餘partitions中的全部nodes,以後重啓這些nodes。當這些nodes從新加入cluster後將從信任的partition恢復狀態。
最後還需重啓信任的partition中的全部nodes以清除network partition的警告信息

Rabbitmq自動處理網絡分區的3種模式

RabbitMQ提供了3種自動處理network partitions的方式:默認爲ignore模式,也即須要手工處理

  1. pause-minority mode:暫停少數模式;
  2. pause-if-all-down mode:暫停-若是所有中止模式
  3. autoheal mode:自動癒合模式

pause-minority mode:暫停少數模式

在pause-minority模式下,察覺其餘nodes down掉後,RabbitMQ將自動暫停認爲本身是少數派的 nodes(例如小於或等於總nodes數的一半),network partition一旦發生,「少數派」的nodes將馬上暫停,直至partition結束後從新恢復。這能夠保證在network partition發生時,至多隻有一個partition中的nodes繼續運行。(犧牲可用性保證一致性)
若全部分區的nodes個數都小於總nodes個數一半,則意味着全部分區的nodes都會認爲本身是少數派,即全部nodes都將暫停;

pause-if-all-down mode:暫停-若是所有中止模式

http://www.rabbitmq.com/partitions.html

autoheal模式

在autoheal模式下一旦發生了partition,RabbitMQ將自動肯定一個優勝partition,而後重啓全部不在優勝partition中的nodes。
獲勝的partition爲擁有最多客戶端鏈接的partition(若鏈接相同則爲節點最多的partition)。
關於自動處理partitions的設置在配置文件的cluster_partition_handling參數中進行。

各自的適用場景

network partitions自動處理並不能保證cluster不出任何問題。
通常來講可做以下選擇:

  • ignore:若網絡很是可靠。全部nodes在同一機架,經過交換機鏈接,該交換機也是通往外部網絡的出口。在cluster的某一部分故障時不但願其他部分受影響。或者cluster只有兩個node。
  • pause_minority:網絡較不可靠。cluster處於EC2的3個AZ中,假定每次至多隻有其中一個AZ故障,想要剩餘的AZ繼續提供服務而故障的AZ中的nodes在AZ恢復後從新自動加入到cluster。
  • autoheal:網絡很不可靠。與數據完整性相比更關注服務的持續性。cluster只有兩個node。

關於pause-minority模式

暫停的nodes上Erlang VM將繼續運行但不監放任何端口或者作其餘工做。它們將每秒檢測一次cluster中的其餘nodes是否可見,若可見則從pause狀態喚醒。 注意: nodes在啓動時不會進入paused狀態,即便是處於「少數派」; RabbitMQ可能會暫停非嚴格意義上的「少數派」中的nodes。如,包含多於總nodes總數一半的nodes。所以在只包含兩個nodes的cluster中使用pause-minority模式並不是好主意,由於在network partition發生或者node失敗時有可能兩個node都會暫停。然而,在包含兩個以上nodes的cluster中pause_minority模式要比ignore更安全; 對於因cluster nodes 掛起引發的partitions pause_minority模式無能爲力。由於掛起的node將不能看到剩餘node是否恢復「可見」,於是不能觸發從cluster中斷開。

相關文章
相關標籤/搜索