MySQL中腦裂是什麼

2022-06-27 14:02:45

在MySQL中,腦裂是指在一個高可用(HA)系統中,當聯絡著的兩個節點斷開聯絡時,本來為一個整體的系統,分裂為兩個獨立節點,這時兩個節點開始爭搶共用資源,結果會導致系統混亂,資料損壞。 對於無狀態服務的HA系統,無所謂腦裂不腦裂;但對有狀態服務(比如MySQL)的HA,必須要嚴格防止腦裂。

本教學操作環境:windows7系統、mysql8版本、Dell G3電腦。

腦裂(split-brain)

指在一個高可用(HA)系統中,當聯絡著的兩個節點斷開聯絡時,本來為一個整體的系統,分裂為兩個獨立節點,這時兩個節點開始爭搶共用資源,結果會導致系統混亂,資料損壞。

在一個高可用性叢集環境中有一個活動節點和一個或多個備用節點,當活動節點發生故障或停止響應時,它們將接管服務。

在考慮節點之間的網路層之前,這聽起來像是一個合理的假設。 如果節點之間的網路路徑出現故障怎麼辦?

任何一個節點現在都不能與另一個節點通訊,在這種情況下,備用伺服器可能會在它認為活動節點發生故障的基礎上將自己提升為活動伺服器。 這導致兩個節點都變得「活躍」,因為每個節點都會認為另一個節點已經死了。 結果,資料完整性和一致性受到損害,因為兩個節點上的資料都會發生變化。 這被稱為「裂腦」 .

對於無狀態服務的HA,無所謂腦裂不腦裂;但對有狀態服務(比如MySQL)的HA,必須要嚴格防止腦裂。(但有些生產環境下的系統按照無狀態服務HA的那一套去設定有狀態服務,結果可想而知...)

如何防止HA叢集腦裂

一般採用2個方法 1)仲裁 當兩個節點出現分歧時,由第3方的仲裁者決定聽誰的。這個仲裁者,可能是一個鎖服務,一個共用盤或者其它什麼東西。

2)fencing 當不能確定某個節點的狀態時,通過fencing把對方幹掉,確保共用資源被完全釋放,前提是必須要有可靠的fence裝置。

理想的情況下,以上兩者一個都不能少。 但是,如果節點沒有使用共用資源,比如基於主從複製的資料庫HA,也可以安全的省掉fence裝置,只保留仲裁。而且很多時候我們的環境裡也沒有可用的fence裝置,比如在雲主機裡。

那麼可不可以省掉仲裁,只留fence裝置呢? 不可以。因為,當兩個節點互相失去聯絡時會同時fencing對方。如果fencing的方式是reboot,那麼兩臺機器就會不停的重新啟動。如果fencing的方式是power off,那麼結局有可能是2個節點同歸於盡,也有可能活下來一個。但是如果兩個節點互相失去聯絡的原因是其中一個節點的網路卡故障,而活下來的正好又是那個有故障的節點,那麼結局一樣是悲劇。 所以,單純的雙節點,無論如何也防止不了腦裂。

如何實現上面的策略

可以自己完全從頭開始實現一套符合上述邏輯的指令碼。推薦使用基於成熟的叢集軟體去搭建,比如Pacemaker+Corosync+合適的資源Agent。Keepalived不太適合用於有狀態服務的HA,即使把仲裁和fence那些東西都加到方案裡,總覺得彆扭。

使用Pacemaker+Corosync的方案也有一些注意事項 1)瞭解資源Agent的功能和原理 瞭解資源Agent的功能和原理,才能知道它適用的場景。比如pgsql的資源Agent是比較完善的,支援同步和非同步流複製,並且可以在兩者之前自動切換,並且可以保證同步複製下資料不會丟失。但目前MySQL的資源Agent就很弱了,沒有使用GTID又沒有紀錄檔補償,很容易丟資料,還是不要用的好,繼續用MHA吧(但是,部署MHA時務必要防範腦裂)。

2)確保法定票數(quorum) quorum可以認為是Pacemkaer自帶的仲裁機制,叢集的所有節點中的多數選出一個協調者,叢集的所有指令都由這個協調者發出,可以完美的杜絕腦裂問題。為了使這套機制有效運轉,叢集中至少有3個節點,並且把no-quorum-policy設定成stop,這也是預設值。(很多教學為了方便演示,都把no-quorum-policy設定成ignore,生產環境如果也這麼搞,又沒有其它仲裁機制,是很危險的!)

但是,如果只有2個節點該怎麼辦?

  • 一是拉一個機子借用一下湊足3個節點,再設定location限制,不讓資源分配到那個節點上。
  • 二是把多個不滿足quorum小叢集拉到一起,組成一個大的叢集,同樣適用location限制控制資源的分配的位置。

但是如果你有很多雙節點叢集,找不到那麼多用於湊數的節點,又不想把這些雙節點叢集拉到一起湊成一個大的叢集(比如覺得不方便管理)。那麼可以考慮第三種方法。 第三種方法是設定一個搶佔資源,以及服務和這個搶佔資源的colocation約束,誰搶到搶佔資源誰提供服務。這個搶佔資源可以是某個鎖服務,比如基於zookeeper包裝一個,或者乾脆自己從頭做一個,就像下面這個例子。這個例子是基於http協定的短連線,更細緻的做法是使用長連線心跳檢測,這樣伺服器端可以及時檢出連線斷開而釋放鎖)但是,一定要同時確保這個搶佔資源的高可用,可以把提供搶佔資源的服務做成lingyig高可用的,也可以簡單點,部署3個服務,雙節點上個部署一個,第三個部署在另外一個專門的仲裁節點上,至少獲取3個鎖中的2個才視為取得了鎖。這個仲裁節點可以為很多叢集提供仲裁服務(因為一個機器只能部署一個Pacemaker範例,否則可以用部署了N個Pacemaker範例的仲裁節點做同樣的事情。但是,如非迫不得已,儘量還是採用前面的方法,即滿足Pacemaker法定票數,這種方法更簡單,可靠。

--------------------------------------------------------------keepalived的腦裂問題----------------------------------------------

1)解決keepalived腦裂問題

檢測思路:正常情況下keepalived的VIP地址是在主節點上的,如果在從節點發現了VIP,就設定報警資訊。指令碼(在從節點上)如下:

[root@slave-ha ~]# vim split-brainc_check.sh
#!/bin/bash
# 檢查腦裂的指令碼,在備節點上進行部署
LB01_VIP=192.168.1.229
LB01_IP=192.168.1.129
LB02_IP=192.168.1.130
while true
do
  ping -c 2 -W 3 $LB01_VIP &>/dev/null
    if [ $? -eq 0 -a `ip add|grep "$LB01_VIP"|wc -l` -eq 1 ];then
        echo "ha is brain."
    else
        echo "ha is ok"
    fi
    sleep 5
done

執行結果如下:
[root@slave-ha ~]# bash check_split_brain.sh 
ha is ok
ha is ok
ha is ok
ha is ok
當發現異常時候的執行結果:
[root@slave-ha ~]# bash check_split_brain.sh 
ha is ok
ha is ok
ha is ok
ha is ok
ha is brain.
ha is brain.

2)曾經碰到的一個keepalived腦裂的問題(如果啟用了iptables,不設定"系統接收VRRP協定"的規則,就會出現腦裂)

曾經在做keepalived+Nginx主備架構的環境時,當重新啟動了備用機器後,發現兩臺機器都拿到了VIP。這也就是意味著出現了keepalived的腦裂現象,檢查了兩臺主機的網路連通狀態,發現網路是好的。然後在備機上抓包:

[root@localhost ~]#  tcpdump -i eth0|grep VRRP  
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode  
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes  
22:10:17.146322 IP 192.168.1.54 > vrrp.mcast.net: VRRPv2, Advertisement, vrid 51, prio 160, authtype simple, intvl 1s, length 20  
22:10:17.146577 IP 192.168.1.96 > vrrp.mcast.net: VRRPv2, Advertisement, vrid 51, prio 50, authtype simple, intvl 1s, length 20  
22:10:17.146972 IP 192.168.1.54 > vrrp.mcast.net: VRRPv2, Advertisement, vrid 51, prio 160, authtype simple, intvl 1s, length 20  
22:10:18.147136 IP 192.168.1.96 > vrrp.mcast.net: VRRPv2, Advertisement, vrid 51, prio 50, authtype simple, intvl 1s, length 20  
22:10:18.147576 IP 192.168.1.54 > vrrp.mcast.net: VRRPv2, Advertisement, vrid 51, prio 160, authtype simple, intvl 1s, length 20  
22:10:25.151399 IP 192.168.1.96 > vrrp.mcast.net: VRRPv2, Advertisement, vrid 51, prio 50, authtype simple, intvl 1s, length 20  
22:10:25.151942 IP 192.168.1.54 > vrrp.mcast.net: VRRPv2, Advertisement, vrid 51, prio 160, authtype simple, intvl 1s, length 20  
22:10:26.151703 IP 192.168.1.96 > vrrp.mcast.net: VRRPv2, Advertisement, vrid 51, prio 50, authtype simple, intvl 1s, length 20  
22:10:26.152623 IP 192.168.1.54 > vrrp.mcast.net: VRRPv2, Advertisement, vrid 51, prio 160, authtype simple, intvl 1s, length 20  
22:10:27.152456 IP 192.168.1.96 > vrrp.mcast.net: VRRPv2, Advertisement, vrid 51, prio 50, authtype simple, intvl 1s, length 20  
22:10:27.153261 IP 192.168.1.54 > vrrp.mcast.net: VRRPv2, Advertisement, vrid 51, prio 160, authtype simple, intvl 1s, length 20  
22:10:28.152955 IP 192.168.1.96 > vrrp.mcast.net: VRRPv2, Advertisement, vrid 51, prio 50, authtype simple, intvl 1s, length 20  
22:10:28.153461 IP 192.168.1.54 > vrrp.mcast.net: VRRPv2, Advertisement, vrid 51, prio 160, authtype simple, intvl 1s, length 20  
22:10:29.153766 IP 192.168.1.96 > vrrp.mcast.net: VRRPv2, Advertisement, vrid 51, prio 50, authtype simple, intvl 1s, length 20  
22:10:29.155652 IP 192.168.1.54 > vrrp.mcast.net: VRRPv2, Advertisement, vrid 51, prio 160, authtype simple, intvl 1s, length 20  
22:10:30.154275 IP 192.168.1.96 > vrrp.mcast.net: VRRPv2, Advertisement, vrid 51, prio 50, authtype simple, intvl 1s, length 20  
22:10:30.154587 IP 192.168.1.54 > vrrp.mcast.net: VRRPv2, Advertisement, vrid 51, prio 160, authtype simple, intvl 1s, length 20  
22:10:31.155042 IP 192.168.1.96 > vrrp.mcast.net: VRRPv2, Advertisement, vrid 51, prio 50, authtype simple, intvl 1s, length 20  
22:10:31.155428 IP 192.168.1.54 > vrrp.mcast.net: VRRPv2, Advertisement, vrid 51, prio 160, authtype simple, intvl 1s, length 20  
22:10:32.155539 IP 192.168.1.96 > vrrp.mcast.net: VRRPv2, Advertisement, vrid 51, prio 50, authtype simple, intvl 1s, length 20  
22:10:32.155986 IP 192.168.1.54 > vrrp.mcast.net: VRRPv2, Advertisement, vrid 51, prio 160, authtype simple, intvl 1s, length 20  
22:10:33.156357 IP 192.168.1.96 > vrrp.mcast.net: VRRPv2, Advertisement, vrid 51, prio 50, authtype simple, intvl 1s, length 20  
22:10:33.156979 IP 192.168.1.54 > vrrp.mcast.net: VRRPv2, Advertisement, vrid 51, prio 160, authtype simple, intvl 1s, length 20  
22:10:34.156801 IP 192.168.1.96 > vrrp.mcast.net: VRRPv2, Advertisement, vrid 51, prio 50, authtype simple, intvl 1s, length 20  
22:10:34.156989 IP 192.168.1.54 > vrrp.mcast.net: VRRPv2, Advertisement, vrid 51, prio 160, authtype simple, intvl 1s, length 20  

備機能接收到master發過來的VRRP廣播,那為什麼還會有腦裂現象?
接著發現重新啟動後iptables開啟著,檢查了防火牆設定。發現系統不接收VRRP協定。
於是修改iptables,新增允許系統接收VRRP協定的設定:
-A INPUT -i lo -j ACCEPT   
-----------------------------------------------------------------------------------------
我自己新增了下面的iptables規則:
-A INPUT -s 192.168.1.0/24 -d 224.0.0.18 -j ACCEPT       #允許組播地址通訊
-A INPUT -s 192.168.1.0/24 -p vrrp -j ACCEPT             #允許VRRP(虛擬路由器冗餘協)通訊
-----------------------------------------------------------------------------------------

最後重新啟動iptables,發現備機上的VIP沒了。
雖然問題解決了,但備機明明能抓到master發來的VRRP廣播包,卻無法改變自身狀態。只能說明網路卡接收到封包是在iptables處理封包之前發生的事情。

3)預防keepalived腦裂問題

1)可以採用第三方仲裁的方法。由於keepalived體系中主備兩臺機器所處的狀態與對方有關。如果主備機器之間的通訊出了網題,就會發生腦裂,此時keepalived體系中會出現雙主的情況,產生資源競爭。 2)一般可以引入仲裁來解決這個問題,即每個節點必須判斷自身的狀態。最簡單的一種操作方法是,在主備的keepalived的組態檔中增加check設定,伺服器週期性地ping一下閘道器,如果ping不通則認為自身有問題 。 3)最容易的是藉助keepalived提供的vrrp_script及track_script實現。如下所示:

# vim /etc/keepalived/keepalived.conf
   ......
   vrrp_script check_local {
    script "/root/check_gateway.sh" 
    interval 5
    }
   ......

   track_script {     
   check_local                   
   }

   指令碼內容:
   # cat /root/check_gateway.sh
   #!/bin/sh
   VIP=$1
   GATEWAY=192.168.1.1 
   /sbin/arping -I em1 -c 5 -s $VIP $GATEWAY &>/dev/null

   check_gateway.sh 就是我們的仲裁邏輯,發現ping不通閘道器,則關閉keepalived service keepalived stop。

4)推薦自己寫指令碼

寫一個while迴圈,每輪ping閘道器,累計連續失敗的次數,當連續失敗達到一定次數則執行service keepalived stop關閉keepalived服務。如果發現又能夠ping通閘道器,再重新啟動keepalived服務。最後在指令碼開頭再加上指令碼是否已經執行的判斷邏輯,將該指令碼加到crontab裡面。

【相關推薦:】

以上就是MySQL中腦裂是什麼的詳細內容,更多請關注TW511.COM其它相關文章!