MySQL高可用之DRBD
- 2019 年 11 月 15 日
- 筆記
版權聲明:本文為博主原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接和本聲明。
本文鏈接:https://blog.csdn.net/wzy0623/article/details/103070764
目錄
一、DRBD簡介
1. 工作原理
2. DRBD 支持的底層設備
3. DRBD資源
4. DRBD 配置工具
5. DRBD與RAID1區別
6. DRBD與共享存儲
二、DRBD安裝配置
1. 實驗環境
2. 配置前準備
3. 下載安裝DRBD
4. 配置DRBD
四、測試MySQL數據同步
五、heartbeat+DRBD+mysql高可用方案
1. 配置
2. 測試
參考:
大多數MySQL高可用解決方案都是基於MySQL自帶的各種複製技術。本質上是將一個實例上的數據更新或事務,在其它實例上進行重放,從而完成數據複製。當生產實例出現問題無法提供服務時,應用連接切換到其它實例,實現數據庫服務持續可用。從這個角度看,使用DRBD實現MySQL高可用的方式則完全不同,它與MySQL複製毫無關係,可以說是另闢蹊徑。
一、DRBD簡介
DRBD的全稱是Distributed Replicated Block Device,即分佈式複製塊設備,是一個用軟件實現的、無共享的、服務器之間鏡像塊設備內容的存儲複製解決方案。DRBD是鏡像塊設備,是按數據位鏡像成一樣的數據塊。簡單說DRBD是實現活動節點存儲數據更動後自動複製到備用節點相應存儲位置的軟件,是一種數據塊級別的物理複製。
1. 工作原理
圖1是官方文檔里給出的DRBD工作棧模型,可以看到DRBD需要運行在各個節點上,且是運行在節點主機的內核中,所以DRBD是內核模塊,在Linux 2.6.33版本起開始整合進內核。

圖1 DRBD 架構
圖1中假設左節點為活動節點(primary),右節點為備用節點(secondary)。左節點接收到數據發往內核的數據通路,DRBD在數據通路中註冊鉤子檢查數據,當發現接收到的數據是發往到自己管理的存儲位置,就複製另一份,一份存儲到本機的DRBD存儲設備,另一份就發給TCP/IP協議棧,通過網卡網絡傳輸到另一節點主機的網上TCP/IP協議棧。而另一節點運行的DRBD模塊同樣在數據通路上檢查數據,當發現傳輸過來的數據時,就存儲到DRBD存儲設備對應的位置。
如果左節點宕機,右節點可以在高可用集群中成為活動節點,把接收到的數據先存儲到本地,當左節點恢復上線時,再把宕機後右節點變動的數據鏡像到左節點。鏡像過程完成後還需要返回成功/失敗的回應消息,這個回應消息可以在傳輸過程中的不同位置返回,如圖上的A/B/C標識位置,可以分為三種複製模式:
- A:Async,異步:本地寫成功後立即返回,數據放在發送buffer中,可能丟失,但傳輸性能好。
- B:Semi sync,半同步:對方接收到數據後,但還沒有落盤前返回。
- C:Sync,同步:本地和對方寫成功落盤確認後返回,數據可靠性高,生產系統一般都採用這種方式。
2. DRBD 支持的底層設備
DRBD需要在底層設備上構建出一個塊設備。對於用戶來說,一個DRBD設備,就像是一塊物理的磁盤,可以在DRBD設備內創建文件系統。DRBD所支持的底層設備類別包括:磁盤或者是磁盤的一個分區;soft raid 設備;LVM的邏輯卷;EVMS(Enterprise Volume Management System,企業卷管理系統)卷;或其它任何塊設備。
3. DRBD資源
DRBD資源定義DRBD管理的存儲空間及相關信息,主要配置以下四個選項:
- 資源名稱:可以是除了空白字符外的任意ACSII碼字符。
- DRBD設備:在雙方節點上,此DRBD設備的設備文件,一般為/dev/drbdN,其主設備號147。
- 磁盤:在雙方節點上,各自提供的存儲設備。
- 網絡配置:雙方數據同步時所使用的網絡屬性。
4. DRBD 配置工具
DRBD主要有以下三個配置工具:
- drbdadm:高級管理工具,管理/etc/drbd.conf,向drbdsetup和drbdmeta發送指令。
- drbdsetup:配置裝載進kernel的DRBD模塊,平時很少直接用。
- drbdmeta:管理META數據結構,平時很少直接用。
5. DRBD與RAID1區別
RAID1也是實現不同存儲設備間的數據鏡像備份,不同的是RAID1各存儲設備是連接一個RAID控制器接入到一台主機上的,而DRBD是通過網絡實現不同節點主機存儲設備數據的鏡像備份。
6. DRBD與共享存儲
如果各節點訪問同一個數據文件都是在同一個存儲空間內的,就是說數據共享的就一份,則這個存儲空間就共享存儲。而DRBD定義上就指出了「無共享」——不同節點存儲設備空間是鏡像,DRBD可以直接應用在主備模型的集群中,也可通過高可用軟件如corosycn應用在雙主模型集群中,不過這就需要DML/OCFS2/GFS2等分佈式集群文件系統為雙主讀寫的時候分配鎖。還有就是DRBD為NFS共享存儲提供高可用鏡像備份。
二、DRBD安裝配置
1. 實驗環境
IP與主機名: 172.16.1.125 node1 172.16.1.126 node2
軟件環境: CentOS Linux release 7.2.1511 (Core) DRBD 9.0.20 MySQL 5.6.14
DRBD: 磁盤分區:/dev/sdb 5G DRBD設備:/dev/drbd0 DRBD資源:mysql mount點:/mnt
2. 配置前準備
在安裝配置DRBD前,需要做一些準備工作,以下步驟需要在兩個節點都執行。
(1)設置靜態IP 編輯網卡配置文件,將BOOTPROTO設置為static,如node1的內容如下:
[root@node1~]#cat /etc/sysconfig/network-scripts/ifcfg-ens32 # Generated by dracut initrd NAME="ens32" DEVICE="ens32" ONBOOT=yes NETBOOT=yes UUID="adb62466-2361-405e-ada9-b48fe7c09546" IPV6INIT=yes BOOTPROTO=static TYPE=Ethernet IPADDR=172.16.1.125 NETMASK=255.255.255.0 GATEWAY=172.16.1.254 DNS1=172.16.1.10
重啟網絡服務:
service network restart
(2)配置域名解析 編輯/etc/hosts文件配置域名解析,如node1的內容如下:
[root@node1~]#cat /etc/hosts 127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4 ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6 172.16.1.125 node1 172.16.1.126 node2
(3)禁用SELINUX與防火牆
- 編輯/etc/selinux/config文件,設置SELINUX=disabled。
- 執行下面的命令禁用防火牆:
systemctl stop firewalld systemctl disable firewalld
(4)設置雙向ssh免密 node1上執行:
ssh-keygen -t rsa ssh-copy-id 172.16.1.126
node2上執行:
ssh-keygen -t rsa ssh-copy-id 172.16.1.125
(5)設置NTP時鐘同步
yum install ntp systemctl enable ntpd.service service ntpd start
3. 下載安裝DRBD
在兩個節點執行以下命令:
# 導入GPG-KEY,用於驗證簽名 rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org # 安裝yum源 yum install https://www.elrepo.org/elrepo-release-7.0-4.el7.elrepo.noarch.rpm # 安裝drbd和內核相關軟件包 yum install -y drbd90-utils kmod-drbd90 kernel* # 因為升級了內核,需要重啟系統 reboot
重啟向內核加載drbd模塊並確認:
[root@node2~]#modprobe drbd [root@node2~]#lsmod | grep drbd drbd_transport_tcp 22144 1 drbd 568697 3 drbd_transport_tcp libcrc32c 12644 4 xfs,drbd,ip_vs,nf_conntrack [root@node2~]#
4. 配置DRBD
DRBD的主配置文件為/etc/drbd.conf,為了管理的便捷性,目前通常會將些配置文件分成多個部分,且都保存至/etc/drbd.d目錄中,主配置文件中僅使用」include」指令將這些配置文件片斷整合起來。通常,/etc/drbd.d目錄中的配置文件為global_common.conf和所有以.res結尾的文件。其中global_common.conf中主要定義global段和common段,而每一個.res的文件用於定義一個資源。
在配置文件中,global段僅能出現一次,且如果所有的配置信息都保存至同一個配置文件中而不分開為多個文件的話,global段必須位於配置文件的最開始處。common段則用於定義被每一個資源默認繼承的參數,可以在資源定義中使用的參數都可以在common段中定義。實際應用中,common段並非必須,但建議將多個資源共享的參數定義為common段中的參數以降低配置文件的複雜度。
resource段則用於定義drbd資源,每個資源通常定義在一個單獨的位於/etc/drbd.d目錄中的以.res結尾的文件中。資源在定義時必須為其命名,名字可以由非空白的ASCII字符組成。每一個資源段的定義中至少要包含兩個host子段,以定義此資源關聯至的節點,其它參數均可以從common段或drbd的默認中進行繼承而無須定義。
下面的操作在node1上完成。(1)查看主配置文件/etc/drbd.conf,內容如下:
[root@node1~]#cat /etc/drbd.conf # You can find an example in /usr/share/doc/drbd.../drbd.conf.example include "drbd.d/global_common.conf"; include "drbd.d/*.res"; [root@node1~]#
/etc/drbd.conf主配置文件裏面配置了包含關係,不需要做任何修改,直接使用即可。(2)配置global_common.conf文件內容如下。
[root@node1~]#cat /etc/drbd.d/global_common.conf global { usage-count no; # 不讓官方統計drbd的使用情況 } common { protocol C; # 使用DRBD的同步協議,數據可靠性高 disk { on-io-error detach; # 配置I/O錯誤處理策略為分離 } }
on-io-error策略可能為以下選項之一:
- detach:這是默認和推薦的選項,如果在節點上發生底層的硬盤I/O錯誤,它會將設備運行在Diskless無盤模式下。
- pass_on:DRBD會將I/O錯誤報告到上層,在主節點上,它會將其報告給掛載的文件系統。
- local-in-error:調用本地磁盤I/O處理程序定義的命令。這需要有相應的local-io-error調用的資源處理程序,給管理員有足夠自由的權力調用local-io-error處理I/O錯誤。
/etc/drbd.d/global_common.conf是全局配置文件,這裡只設置了使用統計量、同步協議、I/O錯誤處理策略三項。該文件中還有一些其它選項,每個選項的含義在安裝後的樣例文件中都有相應說明。
(3)配置資源文件/etc/drbd.d/mysql.res內容如下,資源文件名要和資源名一樣。
[root@node1 ~]# cat /etc/drbd.d/mysql.res resource mysql { # 資源名稱 disk /dev/sdb; # 磁盤分區 device /dev/drbd0; # DRBD設備 meta-disk internal; # 元數據存儲方式 on node1 { device /dev/drbd0; disk /dev/sdb; address 172.16.1.125:7789; # 節點1地址 } on node2 { device /dev/drbd0; disk /dev/sdb; address 172.16.1.126:7789; # 節點2地址 } }
metadata有兩種存儲方式internal和external,存儲方式是在每個resource配置段中指定的。配置成使用internal意味着DRBD把它的metadata和實際生產數據存儲於相同的底層物理設備中。該存儲方式是在設備的最後位置留出一個區域來存儲metadata。
(4)將配置文件遠程複製到node2
scp -rp /etc/drbd.d/* node2:/etc/drbd.d/
(5)初始化設備元數據 分別在兩節點上創建DRBD設備元數據:
drbdadm create-md mysql
(6)啟動DRBD資源 分別在兩節點上啟動DRBD資源:
drbdadm up mysql
(7)查看節點角色 當前兩台均為備機:
[root@node1~]#drbdadm role mysql Secondary
(8)將node1設置primary 在node1執行:
[root@node1~]#drbdadm --force primary mysql [root@node1~]#drbdadm role mysql Primary
Parimary表示資源目前為主,並且可能正在被讀取或寫入,如果不是雙主只會出現在兩個節點中的其中一個節點上。Secondary表示資源目前為從,正常接收對等節點的更新。
(9)在主節點對磁盤進行格式化
[root@node1~]#mkfs.xfs /dev/drbd0 meta-data=/dev/drbd0 isize=512 agcount=4, agsize=327668 blks = sectsz=512 attr=2, projid32bit=1 = crc=1 finobt=0, sparse=0 data = bsize=4096 blocks=1310671, imaxpct=25 = sunit=0 swidth=0 blks naming =version 2 bsize=4096 ascii-ci=0 ftype=1 log =internal log bsize=4096 blocks=2560, version=2 = sectsz=512 sunit=0 blks, lazy-count=1 realtime =none extsz=4096 blocks=0, rtextents=0
因為文件系統的掛載只能在Primary節點進行,所以也只有在設置了主節點後才能對DRBD設備進行格式化,這樣就會連格式化後的全部信息都鏡像到另一個節點。
(10)在主節點掛在設備
mount /dev/drbd0 /mnt
(11)查看狀態 查看兩個節點的磁盤狀態和資源狀態:
[root@node1/mnt]#drbdadm dstate mysql UpToDate/UpToDate [root@node1/mnt]#drbdadm cstate mysql Connected
節點的硬盤有可能為下列狀態之一:
- Diskless:本地沒有塊設備分配給DRBD使用,這表示沒有可用的設備,或者使用drbdadm命令手工分離或是底層的I/O錯誤導致自動分離。
- Attaching:讀取無數據時候的瞬間狀態。
- Failed:本地塊設備報告I/O錯誤的狀態,其下一個狀態為Diskless無盤。
- Negotiating:在已經連接的DRBD設置進行Attach讀取無數據前的瞬間狀態。
- Inconsistent:數據是不一致的,在兩個節點上(初始的完全同步前)這種狀態出現後立即創建一個新的資源。此外,在同步期間在同步目標節點上出現這種狀態。
- Outdated:數據資源是一致的,但是已經過時。
- DUnknown:當對等節點網絡連接不可用時出現這種狀態。
- Consistent:一個沒有連接的節點數據一致。當建立連接時,它決定數據是UpToDate或是Outdated。
- UpToDate:一致的最新的數據狀態,這個狀態為正常狀態。
一個資源可能有以下連接狀態中的一種:
- StandAlone:網絡配置不可用,資源還沒有被連接或是被管理斷開(使用 drbdadm disconnect 命令),或是由於出現認證失敗或是腦裂的情況。
- Disconnecting:斷開只是臨時狀態,下一個狀態是StandAlone獨立的。
- Unconnected:是嘗試連接前的臨時狀態,可能下一個狀態為WFconnection和WFReportParams。
- Timeout:與對等節點連接超時,也是臨時狀態,下一個狀態為Unconected。
- BrokerPipe:與對等節點連接丟失,也是臨時狀態,下一個狀態為Unconected。
- NetworkFailure:與對等節點推動連接後的臨時狀態,下一個狀態為Unconected。
- ProtocolError:與對等節點推動連接後的臨時狀態,下一個狀態為Unconected。
- TearDown:臨時狀態,對等節點關閉,下一個狀態為Unconected。
- WFConnection:等待和對等節點建立網絡連接。
- WFReportParams:已經建立TCP連接,本節點等待從對等節點傳來的第一個網絡包。
- Connected:DRBD已經建立連接,數據鏡像現在可用,節點處於正常狀態。
- StartingSyncS:完全同步,有管理員發起的剛剛開始同步,未來可能的狀態為SyncSource或PausedSyncS。
- StartingSyncT:完全同步,有管理員發起的剛剛開始同步,下一狀態為WFSyncUUID。
- WFBitMapS:部分同步剛剛開始,下一步可能的狀態為SyncSource或PausedSyncS。
- WFBitMapT:部分同步剛剛開始,下一步可能的狀態為WFSyncUUID。
- WFSyncUUID:同步即將開始,下一步可能的狀態為SyncTarget或PausedSyncT。
- SyncSource:以本節點為同步源的同步正在進行。
- SyncTarget:以本節點為同步目標的同步正在進行。
- PausedSyncS:以本地節點是一個持續同步的源,但是目前同步已經暫停,可能是因為另外一個同步正在進行或是使用命令(drbdadm pause-sync)暫停了同步。
- PausedSyncT:以本地節點為持續同步的目標,但是目前同步已經暫停,這可以是因為另外一個同步正在進行或是使用命令(drbdadm pause-sync)暫停了同步。
- VerifyS:以本地節點為驗證源的線上設備驗證正在執行。
- VerifyT:以本地節點為驗證目標的線上設備驗證正在執行。
四、測試MySQL數據同步
1. 將MySQL數據目錄設置為DRBD掛載點
在my.cnf配置文件中修改設置:
datadir = /mnt/
2. 啟動mysql服務
# 停止mysql服務 service mysql stop # 將數據目錄拷貝到掛載點 cp -r /data/* /mnt/ # 將數據目錄的屬主改為MySQL chown -R mysql:mysql /mnt/ # 啟動mysql服務 service mysql start
3. 建立數據庫表
create database db1; use db1; create table t1 (a int); insert into t1 select 1; commit;
4. 手工執行主從切換,驗證數據同步 (1)將node1降為從
service mysql stop umount /mnt drbdadm secondary mysql
(2)將node2升為主,並啟動mysql服務
drbdadm primary mysql mount /dev/drbd0 /mnt chown -R mysql:mysql /mnt service mysql start
(3)驗證數據同步
mysql> select * from db1.t1; +------+ | a | +------+ | 1 | +------+ 1 row in set (0.00 sec)
可以看到數據已經同步,在node2上已經有了新建的庫表數據。
五、heartbeat+DRBD+mysql高可用方案
前面的DRBD環境充其量只是一個容災配置,還算不上高可用方案。設想當主節點的MySQL數據庫出現問題時,需要人為發現故障,並手工執行主從切換,這個過程不可避免的長時間停止服務。要保證主服務器不間斷服務,需要實現自動故障轉移,與DRBD一起使用比較多的是Heartbeat。顧名思義,Heartbeat像是在主從兩個DRBD之間接了一條心跳線,當從節點接收不到主節點的心跳時接管服務。Heartbeat雙機熱備軟件來保證數據庫服務的穩定性和連續性,數據一致性由DRBD來保證。默認情況下只有一台MySQL實例在工作,當主MySQL服務器出現問題後,系統將自動切換到備機上繼續提供服務。這個方案的優點顯而易見:安全性、穩定性、可用性高,出現故障自動切換;但缺點也彰明較著:只有一台服務器提供服務,成本相對較高,不方便擴展,可能會發生腦裂。
1. 配置
實驗環境的架構如圖2所示。

圖2 DRBD+Heartbeat+MySQL 高可用架構
前面已經完成了DRBD+mysql的安裝部署,下面配置heartbeat。heartbeat的安裝參見「https://wxy0327.blog.csdn.net/article/details/81188814#%E4%BA%8C%E3%80%81%E5%AE%89%E8%A3%85Heartbeat」
(1)編輯配置文件ha.cf node1上的ha.cf文件內容如下:
[root@node1 ~]# cat /usr/local/heartbeat/etc/ha.d/ha.cf debugfile /var/log/ha-debug logfile /var/log/ha-log logfacility local0 keepalive 1 deadtime 30 warntime 10 initdead 120 udpport 694 bcast ens32 ucast ens32 172.16.1.126 auto_failback off node node1 node node2 ping 172.16.1.254 respawn hacluster /usr/local/heartbeat/libexec/heartbeat/ipfail apiauth ipfail gid=haclient uid=hacluster [root@node1 ~]#
節點2上的/usr/local/heartbeat/etc/ha.d/ha.cf文件只有一個配置項與節點1不同。
ucast ens32 172.16.1.125
(2)編輯認證文件authkeys 節點1與節點2上的authkeys文件相同,內容如下:
[root@node1 ~]# cat /usr/local/heartbeat/etc/ha.d/authkeys auth 1 1 crc
(3)編輯資源配置文件haresources 所有節點的haresources文件相同,內容如下:
[root@node1 ~]# cat /usr/local/heartbeat/etc/ha.d/haresources node1 IPaddr::172.16.1.101/24/ens32 drbddisk::mysql Filesystem::/dev/drbd0::/mnt::xfs mysql
- node1:主節點的主機名。
- IPaddr::172.16.1.101/24/ens32:用IPaddr腳本配置對外服務的浮動虛擬IP。
- drbddisk::mysql:用drbddisk腳本實現DRBD主從節點資源組的掛載和卸載。該腳本文件為heartbeat自帶,缺省安裝在/etc/ha.d/resource.d/drbddisk。
- Filesystem::/dev/drbd0::/mnt::xfs:用Filesystem腳本實現磁盤掛載和卸載。
- mysql:MySQL啟動腳本。
(4)建立插件軟連接
在兩個節點執行以下命令:
cd /usr/local/heartbeat/etc/ha.d chmod 600 authkeys ln -svf /usr/local/heartbeat/lib64/heartbeat/plugins/RAExec/* /usr/local/heartbeat/lib/heartbeat/plugins/RAExec/ ln -svf /usr/local/heartbeat/lib64/heartbeat/plugins/* /usr/local/heartbeat/lib/heartbeat/plugins/
(5)創建腳本文件 在兩個節點的heartbeat資源目錄下創建腳本文件:
- 創建drbddisk文件:
cp /etc/ha.d/resource.d/drbddisk /usr/local/heartbeat/etc/ha.d/resource.d/
- 創建mysql文件,內容如下:
[root@node1 ~]# more /usr/local/heartbeat/etc/ha.d/resource.d/mysql chown -R mysql:mysql /mnt/ service mysql start
- 創建MySQL服務檢測腳本文件,內容如下:
[root@node1 ~]# more /home/mysql/mysql_check.sh #!/bin/bash . /home/mysql/.bashrc count=1 while true do mysql -uroot -p123456 -S /data/mysql.sock -e "show status;" > /dev/null 2>&1 i=$? ps aux | grep mysqld | grep -v grep > /dev/null 2>&1 j=$? if [ $i = 0 ] && [ $j = 0 ] then sleep 3 else if [ $i = 1 ] && [ $j = 0 ] then sleep 3 else if [ $count -gt 5 ] then break fi let count++ continue fi fi done /etc/init.d/heartbeat stop
(6)啟動heartbeat 在兩個節點上啟動HeartBeat服務,先啟動node1,再啟動node2。
systemctl start heartbeat systemctl enable heartbeat systemctl status heartbeat
如下所示,此時VIP綁定在node1上:

客戶端通過VIP可以正常訪問MySQL:
C:Userswxy>mysql -h172.16.1.101 -uroot -p123456 -e "select * from db1.t1" mysql: [Warning] Using a password on the command line interface can be insecure. +------+ | a | +------+ | 1 | +------+
當啟動heartbeat時同時啟動ipfail來檢測心跳,hacluster為啟動heartbeat時的用戶 ,也就是說ipfail和heartbeat都是用hacluster這個用戶來運行。heartbeat和ipfail進程如下所示:

2. 測試
(1)停掉node1上的mysqld,查看服務是否切換到node2
# 首先啟動mysql檢測腳本,因為heartheat不檢查服務的可用性,需要通過自定義腳本實現 nohup /home/mysql/mysql_check.sh & # 停止mysqld service mysql stop
node1的heartbeat進程停止,VIP和DRBD都切換到node2,客戶端可以正常訪問MySQL,自動切換成功。
(2)停掉node2的heartheat,查看服務是否切換回node1
# 先啟動node1的heartheat systemctl start heartbeat # 停止node2的heartheat,也可以使用 iptables -I INPUT -p icmp -j DROP 禁用 ping systemctl stop heartbeat
node2的heartbeat進程停止,VIP和DRBD都切換回node1,客戶端可以正常訪問MySQL,自動切換成功。
(3)node1重啟,查看服務是否切換到node2
# 先啟動node2的heartheat systemctl start heartbeat # node1重啟 reboot
VIP和DRBD都切換到node2,客戶端可以正常訪問MySQL,自動切換成功。(4)測試腦裂
# 停止node1的heartbeat服務 systemctl stop heartbeat # 停止node2的heartbeat服務 systemctl stop heartbeat # 在node1上添加防火牆策略,拒絕node2的廣播包 iptables -A INPUT -i ens32 -p udp -s 172.16.1.126 --dport 694 -j DROP # 在node2上添加防火牆策略,拒絕node1的廣播包 iptables -A INPUT -i ens32 -p udp -s 172.16.1.125 --dport 694 -j DROP # 啟動node1的heartbeat服務 systemctl start heartbeat # 啟動node2的heartbeat服務 systemctl start heartbeat
在超過initdead定義的時間後,兩個節點都綁定了同一個VIP,都掛載了DRDB盤,都啟動了MySQL服務,都可以進行MySQL的讀寫。它們之間各自為政,不知道對方的存在,出現的腦裂。
由於兩節點之間在指定的時間內,無法互相檢測到對方心跳而各自啟動故障轉移功能,取得了資源以及服務的所有權,此時的兩節點都還活着並作正常運行,這樣會導致資源衝突,最嚴重的就是兩台主機同時佔用一個VIP的地址,當用戶寫入數據的時候可能會分別寫入到兩端,這樣可能會導致兩節點數據不一致或造成數據丟失,這種情況被稱為裂腦。
一般來說,裂腦的發生,主要是由以下的幾個原因導致的:
- 節點對之間心跳線路故障,導致無法正常的通信。
- 節點對上開啟了防火牆阻擋了心跳消息的傳輸。
- 節點對上的心跳網卡地址等信息配置的不正確,導致發送心跳失敗。
- 其它服務配置不當等原因,如心跳的方式不同,心跳廣播衝突,軟件出現了BUG等。
發生腦裂的時候,對業務的影響是及其嚴重的,有的時候甚至是致命的。如:兩節點之間發生腦裂,導致互相競爭同一個IP資源,就如同我們局域網內常見的IP地址衝突一樣,兩個機器就會有一個或者兩個不正常,影響用戶正常訪問服務器。如果是應用在數據庫或者是存儲服務這種極重要的高可用上,那就導致用戶發佈的數據間斷的寫在兩台服務器上的惡果,最終導致數據難以恢復。
實際的生產環境中,我們可以從以下幾個方面來防止裂腦的發生:
- 同時使用串行電纜和以太網電纜連接,同時用兩條心跳線路,這樣一條線路壞了,另一個線路還是好的,依然能傳送消息,這是最簡單的一個方案,也是推薦的防腦裂方法。
- 檢測到裂腦的時候強行的關閉一個心跳節點(需要特殊的節點支持,如stonith,fence),相當於程序上備節點發現心跳線故障,發送關機命令到主節點。
- 做好對裂腦的監控報警,如郵件以及手機短訊等,在問題發生的時候能夠人為的介入到仲裁,降低損失。當然,在實施高可用方案的時候,要根據業務的實際需求確定是否能夠容忍這樣的損失。對於一般的網站業務,這個損失是可控的。
- 啟用磁盤鎖。正在服務一方鎖住共享磁盤,腦裂發生的時候,讓對方完全搶不走共享的磁盤資源。但使用鎖磁盤也會有一個不小的問題,如果佔用共享盤的乙方不主動解鎖,另一方就永遠得不到共享磁盤。現實中介入服務節點突然死機或者崩潰,另一方就永遠不可能執行解鎖命令。後備節點也就截關不了共享的資和應用服務。於是有人在HA中設計了「智能」鎖,正在服務的一方只在發現心跳線全部斷開時才啟用磁盤鎖,平時就不上鎖。
- 報警報在服務器接管之前,給人員處理留足夠的時間就是1分鐘內報警了,但是服務器不接管,而是5分鐘之後接管,接管的時間較長。數據不會丟失,但就是會導致用戶無法寫數據。
- 報警後,不直接自動服務器接管,而是由人員接管。
- 增加仲裁的機制,確定誰該獲得資源,這裏面有幾個參考的思路:增加一個仲裁機制。例如設置參考的IP,當心跳完全斷開的時候,2個節點各自都ping一下參考的IP,不同則表明斷點就出現在本段,這樣就主動放棄競爭,讓能夠ping通參考IP的一端去接管服務。或者通過第三方軟件仲裁誰該獲得資源。

