【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狀態喚醒。
注意:
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中斷開。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM