天天看點

【rabbitmq】RabbitMQ 叢集與網絡分區

網絡分區(network partitions)

​​官網-網絡分區​​

網絡裝置故障導緻的網絡分裂。比如,存在A\B\C\D\E五個節點,A\B處于同一子網,B\C\D處于另外一子網,中間通過交換機相連。若兩個子網間的交換機故障了即發生了網絡分區,A\B和C\D\E便不能通訊。

某些系統是partition-tolerant的,也即,即使發生了網絡分區系統分裂為了多個子系統,整個系統仍能正常工作。

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',[]}]}]      

發生網絡分區的狀态資訊:

[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狀态喚醒。

注意: