作者 | wzy0623
責(zé)編 | 屠敏
出品 | CSDN 博客
大多數(shù)MySQL高可用解決方案都是基于MySQL自帶的各種復(fù)制技術(shù)。本質(zhì)上是將一個(gè)實(shí)例上的數(shù)據(jù)更新或事務(wù),在其它實(shí)例上進(jìn)行重放,從而完成數(shù)據(jù)復(fù)制。當(dāng)生產(chǎn)實(shí)例出現(xiàn)問題無法提供服務(wù)時(shí),應(yīng)用連接切換到其它實(shí)例,實(shí)現(xiàn)數(shù)據(jù)庫服務(wù)持續(xù)可用。從這個(gè)角度看,使用DRBD實(shí)現(xiàn)MySQL高可用的方式則完全不同,它與MySQL復(fù)制毫無關(guān)系,可以說是另辟蹊徑。
DRBD簡介
DRBD的全稱是Distributed Replicated Block Device,即分布式復(fù)制塊設(shè)備,是一個(gè)用軟件實(shí)現(xiàn)的、無共享的、服務(wù)器之間鏡像塊設(shè)備內(nèi)容的存儲(chǔ)復(fù)制解決方案。DRBD是鏡像塊設(shè)備,是按數(shù)據(jù)位鏡像成一樣的數(shù)據(jù)塊。簡單說DRBD是實(shí)現(xiàn)活動(dòng)節(jié)點(diǎn)存儲(chǔ)數(shù)據(jù)更動(dòng)后自動(dòng)復(fù)制到備用節(jié)點(diǎn)相應(yīng)存儲(chǔ)位置的軟件,是一種數(shù)據(jù)塊級(jí)別的物理復(fù)制。
1. 工作原理
圖1是官方文檔里給出的DRBD工作棧模型,可以看到DRBD需要運(yùn)行在各個(gè)節(jié)點(diǎn)上,且是運(yùn)行在節(jié)點(diǎn)主機(jī)的內(nèi)核中,所以DRBD是內(nèi)核模塊,在Linux 2.6.33版本起開始整合進(jìn)內(nèi)核。
圖1 DRBD 架構(gòu)
圖1中假設(shè)左節(jié)點(diǎn)為活動(dòng)節(jié)點(diǎn)(primary),右節(jié)點(diǎn)為備用節(jié)點(diǎn)(secondary)。左節(jié)點(diǎn)接收到數(shù)據(jù)發(fā)往內(nèi)核的數(shù)據(jù)通路,DRBD在數(shù)據(jù)通路中注冊(cè)鉤子檢查數(shù)據(jù),當(dāng)發(fā)現(xiàn)接收到的數(shù)據(jù)是發(fā)往到自己管理的存儲(chǔ)位置,就復(fù)制另一份,一份存儲(chǔ)到本機(jī)的DRBD存儲(chǔ)設(shè)備,另一份就發(fā)給TCP/IP協(xié)議棧,通過網(wǎng)卡網(wǎng)絡(luò)傳輸?shù)搅硪还?jié)點(diǎn)主機(jī)的網(wǎng)上TCP/IP協(xié)議棧。而另一節(jié)點(diǎn)運(yùn)行的DRBD模塊同樣在數(shù)據(jù)通路上檢查數(shù)據(jù),當(dāng)發(fā)現(xiàn)傳輸過來的數(shù)據(jù)時(shí),就存儲(chǔ)到DRBD存儲(chǔ)設(shè)備對(duì)應(yīng)的位置。
如果左節(jié)點(diǎn)宕機(jī),右節(jié)點(diǎn)可以在高可用集群中成為活動(dòng)節(jié)點(diǎn),把接收到的數(shù)據(jù)先存儲(chǔ)到本地,當(dāng)左節(jié)點(diǎn)恢復(fù)上線時(shí),再把宕機(jī)后右節(jié)點(diǎn)變動(dòng)的數(shù)據(jù)鏡像到左節(jié)點(diǎn)。鏡像過程完成后還需要返回成功/失敗的回應(yīng)消息,這個(gè)回應(yīng)消息可以在傳輸過程中的不同位置返回,如圖上的A/B/C標(biāo)識(shí)位置,可以分為三種復(fù)制模式:
- A:Async,異步:本地寫成功后立即返回,數(shù)據(jù)放在發(fā)送buffer中,可能丟失,但傳輸性能好。
- B:Semi sync,半同步:對(duì)方接收到數(shù)據(jù)后,但還沒有落盤前返回。
- C:Sync,同步:本地和對(duì)方寫成功落盤確認(rèn)后返回,數(shù)據(jù)可靠性高,生產(chǎn)系統(tǒng)一般都采用這種方式。
2. DRBD 支持的底層設(shè)備
DRBD需要在底層設(shè)備上構(gòu)建出一個(gè)塊設(shè)備。對(duì)于用戶來說,一個(gè)DRBD設(shè)備,就像是一塊物理的磁盤,可以在DRBD設(shè)備內(nèi)創(chuàng)建文件系統(tǒng)。DRBD所支持的底層設(shè)備類別包括:磁盤或者是磁盤的一個(gè)分區(qū);soft raid 設(shè)備;LVM的邏輯卷;EVMS(Enterprise Volume Management System,企業(yè)卷管理系統(tǒng))卷;或其它任何塊設(shè)備。
3. DRBD資源
DRBD資源定義DRBD管理的存儲(chǔ)空間及相關(guān)信息,主要配置以下四個(gè)選項(xiàng):
- 資源名稱:可以是除了空白字符外的任意ACSII碼字符。
- DRBD設(shè)備:在雙方節(jié)點(diǎn)上,此DRBD設(shè)備的設(shè)備文件,一般為/dev/drbdN,其主設(shè)備號(hào)147。
- 磁盤:在雙方節(jié)點(diǎn)上,各自提供的存儲(chǔ)設(shè)備。
- 網(wǎng)絡(luò)配置:雙方數(shù)據(jù)同步時(shí)所使用的網(wǎng)絡(luò)屬性。
4. DRBD 配置工具
DRBD主要有以下三個(gè)配置工具:
- drbdadm:高級(jí)管理工具,管理/etc/drbd.conf,向drbdsetup和drbdmeta發(fā)送指令。
- drbdsetup:配置裝載進(jìn)kernel的DRBD模塊,平時(shí)很少直接用。
- drbdmeta:管理meta數(shù)據(jù)結(jié)構(gòu),平時(shí)很少直接用。
5. DRBD與RAID1區(qū)別
RAID1也是實(shí)現(xiàn)不同存儲(chǔ)設(shè)備間的數(shù)據(jù)鏡像備份,不同的是RAID1各存儲(chǔ)設(shè)備是連接一個(gè)RAID控制器接入到一臺(tái)主機(jī)上的,而DRBD是通過網(wǎng)絡(luò)實(shí)現(xiàn)不同節(jié)點(diǎn)主機(jī)存儲(chǔ)設(shè)備數(shù)據(jù)的鏡像備份。
6. DRBD與共享存儲(chǔ)
如果各節(jié)點(diǎn)訪問同一個(gè)數(shù)據(jù)文件都是在同一個(gè)存儲(chǔ)空間內(nèi)的,就是說數(shù)據(jù)共享的就一份,則這個(gè)存儲(chǔ)空間就共享存儲(chǔ)。而DRBD定義上就指出了“無共享”——不同節(jié)點(diǎn)存儲(chǔ)設(shè)備空間是鏡像,DRBD可以直接應(yīng)用在主備模型的集群中,也可通過高可用軟件如corosycn應(yīng)用在雙主模型集群中,不過這就需要DML/OCFS2/GFS2等分布式集群文件系統(tǒng)為雙主讀寫的時(shí)候分配鎖。還有就是DRBD為NFS共享存儲(chǔ)提供高可用鏡像備份。
DRBD安裝配置
1. 實(shí)驗(yàn)環(huán)境
IP與主機(jī)名:
172.16.1.125 node1
172.16.1.126 node2
軟件環(huán)境:
CentOS Linux release 7.2.1511 (Core)
DRBD 9.0.20
MySQL 5.6.14
DRBD:
磁盤分區(qū):/dev/sdb 5G
DRBD設(shè)備:/dev/drbd0
DRBD資源:mysql
mount點(diǎn):/mnt
2. 配置前準(zhǔn)備
在安裝配置DRBD前,需要做一些準(zhǔn)備工作,以下步驟需要在兩個(gè)節(jié)點(diǎn)都執(zhí)行。
(1)設(shè)置靜態(tài)IP
編輯網(wǎng)卡配置文件,將BOOTPROTO設(shè)置為static,如node1的內(nèi)容如下:
[root@node1~]#cat /etc/sysconfig/network-s/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
重啟網(wǎng)絡(luò)服務(wù):
servicenetwork restart
(2)配置域名解析
編輯/etc/hosts文件配置域名解析,如node1的內(nèi)容如下:
[root@node1~] #cat /etc/hosts
127.0.0.1localhost localhost.localdomain localhost4 localhost4.localdomain4
:: 1localhost localhost.localdomain localhost6 localhost6.localdomain6
172.16.1.125node1
172.16.1.126node2
(3)禁用SELINUX與防火墻
- 編輯/etc/selinux/config文件,設(shè)置SELINUX=disabled。
- 執(zhí)行下面的命令禁用防火墻:
(4)設(shè)置雙向ssh免密
node1上執(zhí)行:
ssh-keygen-trsa
ssh-copy-id172 .16.1.126
node2上執(zhí)行:
ssh-keygen-trsa
ssh-copy-id172 .16.1.125
(5)設(shè)置NTP時(shí)鐘同步
yum installntp
systemctl enablentpd.service
service ntpd start
3. 下載安裝DRBD
在兩個(gè)節(jié)點(diǎn)執(zhí)行以下命令:
# 導(dǎo)入GPG-KEY,用于驗(yàn)證簽名
rpm --import https://elrepo.org/RPM-GPG-KEY-elrepo.org
# 安裝yum源
yum installhttps://elrepo.org/elrepo- release-7.0-4.el7.elrepo.noarch.rpm
# 安裝drbd和內(nèi)核相關(guān)軟件包
yum install-y drbd90-utils kmod-drbd90 kernel*
# 因?yàn)樯?jí)了內(nèi)核,需要重啟系統(tǒng)
reboot
重啟向內(nèi)核加載drbd模塊并確認(rèn):
[root@node2~] #modprobe drbd
[root@node2~] #lsmod | grep drbd
drbd_transport_tcp 221441
drbd 5686973drbd_transport_tcp
libcrc32c 126444xfs,drbd,ip_vs,nf_conntrack
[root@node2~] #
4. 配置DRBD
DRBD的主配置文件為/etc/drbd.conf,為了管理的便捷性,目前通常會(huì)將些配置文件分成多個(gè)部分,且都保存至/etc/drbd.d目錄中,主配置文件中僅使用”include”指令將這些配置文件片斷整合起來。通常,/etc/drbd.d目錄中的配置文件為global_common.conf和所有以.res結(jié)尾的文件。其中g(shù)lobal_common.conf中主要定義global段和common段,而每一個(gè).res的文件用于定義一個(gè)資源。
在配置文件中,global段僅能出現(xiàn)一次,且如果所有的配置信息都保存至同一個(gè)配置文件中而不分開為多個(gè)文件的話,global段必須位于配置文件的最開始處。common段則用于定義被每一個(gè)資源默認(rèn)繼承的參數(shù),可以在資源定義中使用的參數(shù)都可以在common段中定義。實(shí)際應(yīng)用中,common段并非必須,但建議將多個(gè)資源共享的參數(shù)定義為common段中的參數(shù)以降低配置文件的復(fù)雜度。
resource段則用于定義drbd資源,每個(gè)資源通常定義在一個(gè)單獨(dú)的位于/etc/drbd.d目錄中的以.res結(jié)尾的文件中。資源在定義時(shí)必須為其命名,名字可以由非空白的ASCII字符組成。每一個(gè)資源段的定義中至少要包含兩個(gè)host子段,以定義此資源關(guān)聯(lián)至的節(jié)點(diǎn),其它參數(shù)均可以從common段或drbd的默認(rèn)中進(jìn)行繼承而無須定義。
下面的操作在node1上完成。(1)查看主配置文件/etc/drbd.conf,內(nèi)容如下:
[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主配置文件里面配置了包含關(guān)系,不需要做任何修改,直接使用即可。(2)配置global_common.conf文件內(nèi)容如下。
[root@node1~] #cat /etc/drbd.d/global_common.conf
global{
usage-count no; # 不讓官方統(tǒng)計(jì)drbd的使用情況
}
common {
protocol C; # 使用DRBD的同步協(xié)議,數(shù)據(jù)可靠性高
disk {
on-io-error detach; # 配置I/O錯(cuò)誤處理策略為分離
}
}
on-io-error策略可能為以下選項(xiàng)之一:
- detach:這是默認(rèn)和推薦的選項(xiàng),如果在節(jié)點(diǎn)上發(fā)生底層的硬盤I/O錯(cuò)誤,它會(huì)將設(shè)備運(yùn)行在Diskless無盤模式下。
- pass_on:DRBD會(huì)將I/O錯(cuò)誤報(bào)告到上層,在主節(jié)點(diǎn)上,它會(huì)將其報(bào)告給掛載的文件系統(tǒng)。
- local-in-error:調(diào)用本地磁盤I/O處理程序定義的命令。這需要有相應(yīng)的local-io-error調(diào)用的資源處理程序,給管理員有足夠自由的權(quán)力調(diào)用local-io-error處理I/O錯(cuò)誤。
/etc/drbd.d/global_common.conf是全局配置文件,這里只設(shè)置了使用統(tǒng)計(jì)量、同步協(xié)議、I/O錯(cuò)誤處理策略三項(xiàng)。該文件中還有一些其它選項(xiàng),每個(gè)選項(xiàng)的含義在安裝后的樣例文件中都有相應(yīng)說明。
(3)配置資源文件/etc/drbd.d/mysql.res內(nèi)容如下,資源文件名要和資源名一樣。
[ root@node1 ~] # cat /etc/drbd.d/mysql.res
resource mysql { # 資源名稱
disk /dev/sdb; # 磁盤分區(qū)
device /dev/drbd0; # DRBD設(shè)備
meta-disk internal; # 元數(shù)據(jù)存儲(chǔ)方式
onnode1 {
device /dev/drbd0;
disk /dev/sdb;
address 172.16.1.125: 7789; # 節(jié)點(diǎn)1地址
}
onnode2 {
device /dev/drbd0;
disk /dev/sdb;
address 172.16.1.126: 7789; # 節(jié)點(diǎn)2地址
}
}
metadata有兩種存儲(chǔ)方式internal和external,存儲(chǔ)方式是在每個(gè)resource配置段中指定的。配置成使用internal意味著DRBD把它的metadata和實(shí)際生產(chǎn)數(shù)據(jù)存儲(chǔ)于相同的底層物理設(shè)備中。該存儲(chǔ)方式是在設(shè)備的最后位置留出一個(gè)區(qū)域來存儲(chǔ)metadata。
(4)將配置文件遠(yuǎn)程復(fù)制到node2
scp -rp /etc/drbd.d/* node2: /etc/drbd.d/
(5)初始化設(shè)備元數(shù)據(jù)
分別在兩節(jié)點(diǎn)上創(chuàng)建DRBD設(shè)備元數(shù)據(jù):
drbdadmcreate-md mysql
(6)啟動(dòng)DRBD資源
分別在兩節(jié)點(diǎn)上啟動(dòng)DRBD資源:
drbdadmup mysql
(7)查看節(jié)點(diǎn)角色
當(dāng)前兩臺(tái)均為備機(jī):
[root@node1~] #drbdadm role mysql
Secondary
(8)將node1設(shè)置primary
在node1執(zhí)行:
[root@node1~] #drbdadm --force primary mysql
[root@node1~] #drbdadm role mysql
Primary
Parimary表示資源目前為主,并且可能正在被讀取或?qū)懭耄绻皇请p主只會(huì)出現(xiàn)在兩個(gè)節(jié)點(diǎn)中的其中一個(gè)節(jié)點(diǎn)上。Secondary表示資源目前為從,正常接收對(duì)等節(jié)點(diǎn)的更新。
(9)在主節(jié)點(diǎn)對(duì)磁盤進(jìn)行格式化
[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
因?yàn)槲募到y(tǒng)的掛載只能在Primary節(jié)點(diǎn)進(jìn)行,所以也只有在設(shè)置了主節(jié)點(diǎn)后才能對(duì)DRBD設(shè)備進(jìn)行格式化,這樣就會(huì)連格式化后的全部信息都鏡像到另一個(gè)節(jié)點(diǎn)。
(10)在主節(jié)點(diǎn)掛在設(shè)備
mount/dev/drbd0 /mnt
(11)查看狀態(tài)
查看兩個(gè)節(jié)點(diǎn)的磁盤狀態(tài)和資源狀態(tài):
[root@node1/mnt] #drbdadm dstate mysql
UpToDate/UpToDate
[root@node1/mnt] #drbdadm cstate mysql
Connected
節(jié)點(diǎn)的硬盤有可能為下列狀態(tài)之一:
- Diskless:本地沒有塊設(shè)備分配給DRBD使用,這表示沒有可用的設(shè)備,或者使用drbdadm命令手工分離或是底層的I/O錯(cuò)誤導(dǎo)致自動(dòng)分離。
- Attaching:讀取無數(shù)據(jù)時(shí)候的瞬間狀態(tài)。
- Failed:本地塊設(shè)備報(bào)告I/O錯(cuò)誤的狀態(tài),其下一個(gè)狀態(tài)為Diskless無盤。
- Negotiating:在已經(jīng)連接的DRBD設(shè)置進(jìn)行Attach讀取無數(shù)據(jù)前的瞬間狀態(tài)。
- Inconsistent:數(shù)據(jù)是不一致的,在兩個(gè)節(jié)點(diǎn)上(初始的完全同步前)這種狀態(tài)出現(xiàn)后立即創(chuàng)建一個(gè)新的資源。此外,在同步期間在同步目標(biāo)節(jié)點(diǎn)上出現(xiàn)這種狀態(tài)。
- Outdated:數(shù)據(jù)資源是一致的,但是已經(jīng)過時(shí)。
- DUnknown:當(dāng)對(duì)等節(jié)點(diǎn)網(wǎng)絡(luò)連接不可用時(shí)出現(xiàn)這種狀態(tài)。
- Consistent:一個(gè)沒有連接的節(jié)點(diǎn)數(shù)據(jù)一致。當(dāng)建立連接時(shí),它決定數(shù)據(jù)是UpToDate或是Outdated。
- UpToDate:一致的最新的數(shù)據(jù)狀態(tài),這個(gè)狀態(tài)為正常狀態(tài)。
一個(gè)資源可能有以下連接狀態(tài)中的一種:
- StandAlone:網(wǎng)絡(luò)配置不可用,資源還沒有被連接或是被管理斷開(使用 drbdadm disconnect 命令),或是由于出現(xiàn)認(rèn)證失敗或是腦裂的情況。
- Disconnecting:斷開只是臨時(shí)狀態(tài),下一個(gè)狀態(tài)是StandAlone獨(dú)立的。
- Unconnected:是嘗試連接前的臨時(shí)狀態(tài),可能下一個(gè)狀態(tài)為WFconnection和WFReportParams。
- Timeout:與對(duì)等節(jié)點(diǎn)連接超時(shí),也是臨時(shí)狀態(tài),下一個(gè)狀態(tài)為Unconected。
- BrokerPipe:與對(duì)等節(jié)點(diǎn)連接丟失,也是臨時(shí)狀態(tài),下一個(gè)狀態(tài)為Unconected。
- NetworkFailure:與對(duì)等節(jié)點(diǎn)推動(dòng)連接后的臨時(shí)狀態(tài),下一個(gè)狀態(tài)為Unconected。
- ProtocolError:與對(duì)等節(jié)點(diǎn)推動(dòng)連接后的臨時(shí)狀態(tài),下一個(gè)狀態(tài)為Unconected。
- TearDown:臨時(shí)狀態(tài),對(duì)等節(jié)點(diǎn)關(guān)閉,下一個(gè)狀態(tài)為Unconected。
- WFConnection:等待和對(duì)等節(jié)點(diǎn)建立網(wǎng)絡(luò)連接。
- WFReportParams:已經(jīng)建立TCP連接,本節(jié)點(diǎn)等待從對(duì)等節(jié)點(diǎn)傳來的第一個(gè)網(wǎng)絡(luò)包。
- Connected:DRBD已經(jīng)建立連接,數(shù)據(jù)鏡像現(xiàn)在可用,節(jié)點(diǎn)處于正常狀態(tài)。
- StartingSyncS:完全同步,有管理員發(fā)起的剛剛開始同步,未來可能的狀態(tài)為SyncSource或PausedSyncS。
- StartingSyncT:完全同步,有管理員發(fā)起的剛剛開始同步,下一狀態(tài)為WFSyncUUID。
- WFBitMapS:部分同步剛剛開始,下一步可能的狀態(tài)為SyncSource或PausedSyncS。
- WFBitMapT:部分同步剛剛開始,下一步可能的狀態(tài)為WFSyncUUID。
- WFSyncUUID:同步即將開始,下一步可能的狀態(tài)為SyncTarget或PausedSyncT。
- SyncSource:以本節(jié)點(diǎn)為同步源的同步正在進(jìn)行。
- SyncTarget:以本節(jié)點(diǎn)為同步目標(biāo)的同步正在進(jìn)行。
- PausedSyncS:以本地節(jié)點(diǎn)是一個(gè)持續(xù)同步的源,但是目前同步已經(jīng)暫停,可能是因?yàn)榱硗庖粋€(gè)同步正在進(jìn)行或是使用命令(drbdadm pause-sync)暫停了同步。
- PausedSyncT:以本地節(jié)點(diǎn)為持續(xù)同步的目標(biāo),但是目前同步已經(jīng)暫停,這可以是因?yàn)榱硗庖粋€(gè)同步正在進(jìn)行或是使用命令(drbdadm pause-sync)暫停了同步。
- VerifyS:以本地節(jié)點(diǎn)為驗(yàn)證源的線上設(shè)備驗(yàn)證正在執(zhí)行。
- VerifyT:以本地節(jié)點(diǎn)為驗(yàn)證目標(biāo)的線上設(shè)備驗(yàn)證正在執(zhí)行。
測試MySQL數(shù)據(jù)同步
1. 將MySQL數(shù)據(jù)目錄設(shè)置為DRBD掛載點(diǎn)
在myf配置文件中修改設(shè)置:
datadir= /mnt/
2. 啟動(dòng)mysql服務(wù)
# 停止mysql服務(wù)
service mysql stop
# 將數(shù)據(jù)目錄拷貝到掛載點(diǎn)
cp -r /data/* /mnt/
# 將數(shù)據(jù)目錄的屬主改為MySQL
chown -R mysql:mysql /mnt/
# 啟動(dòng)mysql服務(wù)
service mysql start
3. 建立數(shù)據(jù)庫表
createdatabasedb1;
usedb1;
createtablet1 (a int);
insertintot1 select1;
commit;
4. 手工執(zhí)行主從切換,驗(yàn)證數(shù)據(jù)同步
(1)將node1降為從
servicemysql stop
umount /mnt
drbdadm secondary mysql
(2)將node2升為主,并啟動(dòng)mysql服務(wù)
drbdadmprimary mysql
mount /dev/drbd0 /mnt
chown -R mysql:mysql /mnt
service mysql start
(3)驗(yàn)證數(shù)據(jù)同步
mysql> select* from db1.t1;
+ ------+
| a |
+ ------+
| 1|
+ ------+
1row inset ( 0.00sec)
可以看到數(shù)據(jù)已經(jīng)同步,在node2上已經(jīng)有了新建的庫表數(shù)據(jù)。
heartbeat+DRBD+mysql高可用方案
前面的DRBD環(huán)境充其量只是一個(gè)容災(zāi)配置,還算不上高可用方案。設(shè)想當(dāng)主節(jié)點(diǎn)的MySQL數(shù)據(jù)庫出現(xiàn)問題時(shí),需要人為發(fā)現(xiàn)故障,并手工執(zhí)行主從切換,這個(gè)過程不可避免的長時(shí)間停止服務(wù)。要保證主服務(wù)器不間斷服務(wù),需要實(shí)現(xiàn)自動(dòng)故障轉(zhuǎn)移,與DRBD一起使用比較多的是Heartbeat。顧名思義,Heartbeat像是在主從兩個(gè)DRBD之間接了一條心跳線,當(dāng)從節(jié)點(diǎn)接收不到主節(jié)點(diǎn)的心跳時(shí)接管服務(wù)。Heartbeat雙機(jī)熱備軟件來保證數(shù)據(jù)庫服務(wù)的穩(wěn)定性和連續(xù)性,數(shù)據(jù)一致性由DRBD來保證。默認(rèn)情況下只有一臺(tái)MySQL實(shí)例在工作,當(dāng)主MySQL服務(wù)器出現(xiàn)問題后,系統(tǒng)將自動(dòng)切換到備機(jī)上繼續(xù)提供服務(wù)。這個(gè)方案的優(yōu)點(diǎn)顯而易見:安全性、穩(wěn)定性、可用性高,出現(xiàn)故障自動(dòng)切換;但缺點(diǎn)也彰明較著:只有一臺(tái)服務(wù)器提供服務(wù),成本相對(duì)較高,不方便擴(kuò)展,可能會(huì)發(fā)生腦裂。
1. 配置
實(shí)驗(yàn)環(huán)境的架構(gòu)如圖2所示。
圖2 DRBD+Heartbeat+MySQL 高可用架構(gòu)
前面已經(jīng)完成了DRBD+mysql的安裝部署,下面配置heartbeat。heartbeat的安裝參見“https://wxy0327.blog.csdn/article/details/81188814#%E4%BA%8C%E3%80%81%E5%AE%89%E8%A3%85Heartbeat”
(1)編輯配置文件ha.cf
node1上的ha.cf文件內(nèi)容如下:
[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 ~] #
節(jié)點(diǎn)2上的/usr/local/heartbeat/etc/ha.d/ha.cf文件只有一個(gè)配置項(xiàng)與節(jié)點(diǎn)1不同。
ucastens32172 .16.1.125
(2)編輯認(rèn)證文件authkeys
節(jié)點(diǎn)1與節(jié)點(diǎn)2上的authkeys文件相同,內(nèi)容如下:
[root@node1 ~] # cat /usr/local/heartbeat/etc/ha.d/authkeys
auth 1
1crc
(3)編輯資源配置文件haresources
所有節(jié)點(diǎn)的haresources文件相同,內(nèi)容如下:
[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:主節(jié)點(diǎn)的主機(jī)名。
IPaddr::172.16.1.101/24/ens32:用IPaddr腳本配置對(duì)外服務(wù)的浮動(dòng)虛擬IP。
drbddisk::mysql:用drbddisk腳本實(shí)現(xiàn)DRBD主從節(jié)點(diǎn)資源組的掛載和卸載。該腳本文件為heartbeat自帶,缺省安裝在/etc/ha.d/resource.d/drbddisk。
Filesystem::/dev/drbd0::/mnt::xfs:用Filesystem腳本實(shí)現(xiàn)磁盤掛載和卸載。
mysql:MySQL啟動(dòng)腳本。
(4)建立插件軟連接
在兩個(gè)節(jié)點(diǎn)執(zhí)行以下命令:
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)創(chuàng)建腳本文件
在兩個(gè)節(jié)點(diǎn)的heartbeat資源目錄下創(chuàng)建腳本文件:
創(chuàng)建drbddisk文件:
cp /etc/ha.d/resource.d/drbddisk /usr/ local/heartbeat/etc/ha.d/resource.d/
創(chuàng)建mysql文件,內(nèi)容如下:
[root@node1 ~] # more /usr/local/heartbeat/etc/ha.d/resource.d/mysql
chown -R mysql:mysql /mnt/
service mysql start
創(chuàng)建MySQL服務(wù)檢測腳本文件,內(nèi)容如下:
[root@node1 ~] # more /home/mysql/mysql_check.sh
#!/bin/bash
. /home/mysql/.bashrc
count=1
whiletrue
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
letcount++
continue
fi
fi
done
/etc/init.d/heartbeat stop
(6)啟動(dòng)heartbeat
在兩個(gè)節(jié)點(diǎn)上啟動(dòng)HeartBeat服務(wù),先啟動(dòng)node1,再啟動(dòng)node2。
systemctl startheartbeat
systemctl enableheartbeat
systemctl statusheartbeat
如下所示,此時(shí)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|
+ ------+
當(dāng)啟動(dòng)heartbeat時(shí)同時(shí)啟動(dòng)ipfail來檢測心跳,hacluster為啟動(dòng)heartbeat時(shí)的用戶 ,也就是說ipfail和heartbeat都是用hacluster這個(gè)用戶來運(yùn)行。heartbeat和ipfail進(jìn)程如下所示:
2. 測試
(1)停掉node1上的mysqld,查看服務(wù)是否切換到node2
# 首先啟動(dòng)mysql檢測腳本,因?yàn)閔eartheat不檢查服務(wù)的可用性,需要通過自定義腳本實(shí)現(xiàn)
nohup/home/mysql/mysql_check.sh &
# 停止mysqld
service mysql stop
node1的heartbeat進(jìn)程停止,VIP和DRBD都切換到node2,客戶端可以正常訪問MySQL,自動(dòng)切換成功。
(2)停掉node2的heartheat,查看服務(wù)是否切換回node1
# 先啟動(dòng)node1的heartheat
systemctl startheartbeat
# 停止node2的heartheat,也可以使用 iptables -I INPUT -p icmp -j DROP 禁用 ping
systemctl stopheartbeat
node2的heartbeat進(jìn)程停止,VIP和DRBD都切換回node1,客戶端可以正常訪問MySQL,自動(dòng)切換成功。
(3)node1重啟,查看服務(wù)是否切換到node2
# 先啟動(dòng)node2的heartheat
systemctlstart heartbeat
# node1重啟
reboot
VIP和DRBD都切換到node2,客戶端可以正常訪問MySQL,自動(dòng)切換成功。
(4)測試腦裂
# 停止node1的heartbeat服務(wù)
systemctl stopheartbeat
# 停止node2的heartbeat服務(wù)
systemctl stopheartbeat
# 在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
# 啟動(dòng)node1的heartbeat服務(wù)
systemctl startheartbeat
# 啟動(dòng)node2的heartbeat服務(wù)
systemctl startheartbeat
在超過initdead定義的時(shí)間后,兩個(gè)節(jié)點(diǎn)都綁定了同一個(gè)VIP,都掛載了DRDB盤,都啟動(dòng)了MySQL服務(wù),都可以進(jìn)行MySQL的讀寫。它們之間各自為政,不知道對(duì)方的存在,出現(xiàn)的腦裂。
由于兩節(jié)點(diǎn)之間在指定的時(shí)間內(nèi),無法互相檢測到對(duì)方心跳而各自啟動(dòng)故障轉(zhuǎn)移功能,取得了資源以及服務(wù)的所有權(quán),此時(shí)的兩節(jié)點(diǎn)都還活著并作正常運(yùn)行,這樣會(huì)導(dǎo)致資源沖突,最嚴(yán)重的就是兩臺(tái)主機(jī)同時(shí)占用一個(gè)VIP的地址,當(dāng)用戶寫入數(shù)據(jù)的時(shí)候可能會(huì)分別寫入到兩端,這樣可能會(huì)導(dǎo)致兩節(jié)點(diǎn)數(shù)據(jù)不一致或造成數(shù)據(jù)丟失,這種情況被稱為裂腦。
一般來說,裂腦的發(fā)生,主要是由以下的幾個(gè)原因?qū)е碌模?/p>
- 節(jié)點(diǎn)對(duì)之間心跳線路故障,導(dǎo)致無法正常的通信。
- 節(jié)點(diǎn)對(duì)上開啟了防火墻阻擋了心跳消息的傳輸。
- 節(jié)點(diǎn)對(duì)上的心跳網(wǎng)卡地址等信息配置的不正確,導(dǎo)致發(fā)送心跳失敗。
- 其它服務(wù)配置不當(dāng)?shù)仍颍缧奶姆绞讲煌奶鴱V播沖突,軟件出現(xiàn)了BUG等。
發(fā)生腦裂的時(shí)候,對(duì)業(yè)務(wù)的影響是及其嚴(yán)重的,有的時(shí)候甚至是致命的。如:兩節(jié)點(diǎn)之間發(fā)生腦裂,導(dǎo)致互相競爭同一個(gè)IP資源,就如同我們局域網(wǎng)內(nèi)常見的IP地址沖突一樣,兩個(gè)機(jī)器就會(huì)有一個(gè)或者兩個(gè)不正常,影響用戶正常訪問服務(wù)器。如果是應(yīng)用在數(shù)據(jù)庫或者是存儲(chǔ)服務(wù)這種極重要的高可用上,那就導(dǎo)致用戶發(fā)布的數(shù)據(jù)間斷的寫在兩臺(tái)服務(wù)器上的惡果,最終導(dǎo)致數(shù)據(jù)難以恢復(fù)。
實(shí)際的生產(chǎn)環(huán)境中,我們可以從以下幾個(gè)方面來防止裂腦的發(fā)生:
- 同時(shí)使用串行電纜和以太網(wǎng)電纜連接,同時(shí)用兩條心跳線路,這樣一條線路壞了,另一個(gè)線路還是好的,依然能傳送消息,這是最簡單的一個(gè)方案,也是推薦的防腦裂方法。
- 檢測到裂腦的時(shí)候強(qiáng)行的關(guān)閉一個(gè)心跳節(jié)點(diǎn)(需要特殊的節(jié)點(diǎn)支持,如stonith,fence),相當(dāng)于程序上備節(jié)點(diǎn)發(fā)現(xiàn)心跳線故障,發(fā)送關(guān)機(jī)命令到主節(jié)點(diǎn)。
- 做好對(duì)裂腦的監(jiān)控報(bào)警,如郵件以及手機(jī)短信等,在問題發(fā)生的時(shí)候能夠人為的介入到仲裁,降低損失。當(dāng)然,在實(shí)施高可用方案的時(shí)候,要根據(jù)業(yè)務(wù)的實(shí)際需求確定是否能夠容忍這樣的損失。對(duì)于一般的網(wǎng)站業(yè)務(wù),這個(gè)損失是可控的。
- 啟用磁盤鎖。正在服務(wù)一方鎖住共享磁盤,腦裂發(fā)生的時(shí)候,讓對(duì)方完全搶不走共享的磁盤資源。但使用鎖磁盤也會(huì)有一個(gè)不小的問題,如果占用共享盤的乙方不主動(dòng)解鎖,另一方就永遠(yuǎn)得不到共享磁盤。現(xiàn)實(shí)中介入服務(wù)節(jié)點(diǎn)突然死機(jī)或者崩潰,另一方就永遠(yuǎn)不可能執(zhí)行解鎖命令。后備節(jié)點(diǎn)也就截關(guān)不了共享的資和應(yīng)用服務(wù)。于是有人在HA中設(shè)計(jì)了“智能”鎖,正在服務(wù)的一方只在發(fā)現(xiàn)心跳線全部斷開時(shí)才啟用磁盤鎖,平時(shí)就不上鎖。
- 報(bào)警報(bào)在服務(wù)器接管之前,給人員處理留足夠的時(shí)間就是1分鐘內(nèi)報(bào)警了,但是服務(wù)器不接管,而是5分鐘之后接管,接管的時(shí)間較長。數(shù)據(jù)不會(huì)丟失,但就是會(huì)導(dǎo)致用戶無法寫數(shù)據(jù)。
- 報(bào)警后,不直接自動(dòng)服務(wù)器接管,而是由人員接管。
- 增加仲裁的機(jī)制,確定誰該獲得資源,這里面有幾個(gè)參考的思路:增加一個(gè)仲裁機(jī)制。例如設(shè)置參考的IP,當(dāng)心跳完全斷開的時(shí)候,2個(gè)節(jié)點(diǎn)各自都ping一下參考的IP,不同則表明斷點(diǎn)就出現(xiàn)在本段,這樣就主動(dòng)放棄競爭,讓能夠ping通參考IP的一端去接管服務(wù)。或者通過第三方軟件仲裁誰該獲得資源。
參考:
版權(quán)聲明:本文為CSDN博主「wzy0623」加入原力計(jì)劃的原創(chuàng)文章。
【成就一億技術(shù)人】
即日起至12.24日,
CSDN協(xié)調(diào)更多流量給優(yōu)秀原創(chuàng)作者!詳情請(qǐng)戳下方二維碼~~
年底了,給用心寫技術(shù)文章的同學(xué)意思意思
?馬云穿布鞋演講,任正非打的出行,盤點(diǎn)科技大佬們令人發(fā)指的節(jié)儉生活


