preface
近來公司利潤上升,購買了10幾台服務器,趁此機會,把mysql的主從同步的架構進一步擴展,為了適應日益增長的流量。針對mysql架構的擴展,先是咨詢前輩,后和同事探討,准備采用Mysql+heartbeat+drbd+lvs的方案。
Mysql+heartbeat+drbd+lvs是一套成熟的集群解決方案在現在多數企業里面,通過heartbeat+DRBD完成Mysql的主節點寫操作的高可用性,通過Mysql+lvs實現Mysql數據庫的主從復制和Mysql讀寫的負載均衡。這個方案在讀寫方面進行了分離,融合了寫操作的高可用和讀操作的負載均衡。
有問題請聯系本人郵箱18500777133@sina.cn (溫柔易淡),博客地址為http://www.cnblogs.com/liaojiafa
mysql 高可用集群概述
很多解決方案能夠實現不同的SLA(服務水平協定),這些方案可以保證數據庫服務器高可用性。
那么就說說目前比較流行的高可用解決方案如下幾種:
- Mysql的主從復制功能是通過建立復制關系的多台或多台機器環境中,一台宕機就切換到另一台服務器上,保證mysql的可用性,可以實現90.000%的SLA。
- mysql的復制功能加一些集群軟件可以實現95.000%的SLA。
- Mysql+heartbeat+DRBD的復制功能可以實現99.999%的SLA。
- 共享存儲+MYSQL復制功能可以實現99.990%的SLA
- Mysql cluster的標准版和電信版可以達到99.999%的SLA。
在上述方案中,對於Mysql來說,使用共享存儲的相對較少,使用方法最多的就是heartbeat+drbd+mysql cluster的方案。
DRBD原理闡述
DRBD官網:http://www.drbd.org/en/doc/users-guide-90
DRBD的英文全稱是Distributed Replicated Block Deivce(分布式塊設備復制),是linux內核的存儲層一個分布式存儲系統。可以利用DRBD在兩台服務器之間共享塊設備,文件系統和數據。類似於一個網絡RAID1的功能。
它有三個特點:
- 實時復制:一端修改后馬上復制過去。
- 透明的傳輸: 應用程序不需要感知(或者認識)到這個數據存儲在多個主機上。
- 同步或者異步通過:同步鏡像,應用程序寫完成后會通知所有已連接的主機;異步同步;應用程序會在本地寫完之前通知其他的主機。
他有三個協議
- A 寫I/O達到本地磁盤和本地的TCP發送發送緩存區后,返回操作成功。
- B 寫I/O達到本地磁盤和遠程節點的緩存區之后,返回操作成功。
- C 寫I/O達到本地磁盤和遠程節點的磁盤之后,返回操作成功。
架構圖如下所示:

當數據寫入到本地主節點的文件系統時,這些數據會通過網絡發送到另一台主節點上。本地節點和遠程節點數據通過TCP/IP協議保持同步,主節點故障時,遠程節點保存着相同的數據,可以接替主節點繼續提供數據。兩個節點之間通過使用heartbeat來檢測對方是否存活。
同步過程如下
左為node1,右為node2
- 在NODE1上寫操作被提交,然后通過內核傳給DRBD模塊。
- DRBD發送寫操作到NODE2。
- NODE2上的DRBD發送寫操作給本地磁盤
- 在node2上的DRBD向node1發送確認信息,確認已經收到寫操作並發給本地磁盤。
- NODE1上的DRBD發送寫操作給本地磁盤。
- NODE1上的內核回應寫操作完成。
部署Mysql高可用擴展集群
公司Mysql集群具備高可用,可以擴展,易管理,低成本的特點。通常采用Mysql讀寫分離的方法,而讀寫之間的數據同步采用Mysql的單向或者雙向復制技術實現。Mysql寫操作一般采用基於heartbeat+DRBD+MYSQL搭建高可用集群的方案,而讀操作普遍采用基於LVS+keepalived搭建高可用擴展集群方案。
下面是我們環境的設備信息
| 主機名 | IP | 角色 |
|---|---|---|
| dbmaster81 | 172.16.22.81 | heartbeat+DRBD+Mysql的主節點 |
| dbbackup136 | 172.16.22.136 | heartbeat+DRBD+Mysql的備節點 |
| dbrepslave142 | 172.16.22.142 | mysql-salve,master_host=172.16.160.251 |
| dbrepslave134 | 172.16.22.134 | mysql-salve,master_host=172.16.160.251 |
| lvsmaster162 | 172.16.22.162 | lvs+keepalived master |
| lvsbackup163 | 172.16.160.163 | lvs+keepalived backup |
- keepalived 所使用的IP為 172.16.22.251
- heartbeat 所使用的IP為172.16.22.250
- lvs 對應的realserver 為 172.16.22.142和172.16.22.134
- 以上都是CentOs6.6的系統
Notice
如果讀取的流量非常大,我們還可以考慮在LVS前面加一個Memcached,使其Memcached作為Mysql讀數據的一層緩沖層。至於如何讓Memcached與Mysql進行聯動,請參考我的另一篇博文:http://www.cnblogs.com/liaojiafa/p/6029313.html
架構圖如下:

基礎工作要到位
1. /etc/hosts
所有服務器的/etc/hosts這個文件必須包含所有主機名和主機IP。如下所示:
[root@dbmaster81 ~]# cat /etc/hosts
127.0.0.1 mfsmaster localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
172.16.22.162 lvsmaster162
172.16.22.163 lvsbackup163
172.16.22.142 dbrepslave142
172.16.22.134 dbrepslave134
172.16.22.81 dbmaster81
172.16.22.136 dbbackup136
2. 磁盤分區
數據服務器最好划分一個塊單獨的分區給數據庫文件使用。包含mysql的datadir目錄,binlog文件,relay log文件,my.cnf文件,以及ibd文件(單獨表空間),ibdata文件和ib_logfile文件。互為主備或者同一集群下面 最好磁盤分區一致。避免磁盤空間大小不同導致出現的問題。
3. 網絡環境
咱們使用DRBD進行同步的網絡狀況是否良好。DRBD同步操作對網絡環境要求很好,特別是在寫入大量數據的時候,網絡越好同步速度和可靠性越高。可以考慮把DB對外服務和DRBD同步網絡分開,使他們不會互相干擾。關於心跳線的,兩台服務器之間最好為2根,這樣不會一根線故障導致VIP的切換。在要求較高的環境下,都要求3根心跳線進程心跳檢測,以此減少誤切換和腦裂的問題,同時要確認上層交換機是否禁止ARP廣播。
開始部署
DRBD的部署
可以采用源碼安裝或者yum安裝,我這邊為了更方便就采用yum安裝,源碼安裝比較麻煩了。
首先安裝yum源,然后再安裝BRBD,yum參考文檔:http://www.drbd.org/en/doc/users-guide-84/s-distro-packages
在172.16.22.81上安裝drbd
[root@dbmaster81 ~]# yum update kernel-devel kernel # 先升級內核,不然安裝不上DRBD,我的內核舊的是(2.6.32-504.el6.x86_64),升級后的是2.6.32-642.11.1.el6.x86_64。
[root@dbmaster81 ~]# reboot # 啟動之前先檢測當前使用的內核版本,同時確認grub.conf里面默認啟動的是新內核
[root@dbmaster81 ~]# rpm -Uvh http://www.elrepo.org/elrepo-release-6-6.el6.elrepo.noarch.rpm
[root@dbmaster191 ~]# ls /etc/yum.repos.d/ # 下面是yum源
CentOS-Base.repo CentOS-Debuginfo.repo CentOS-fasttrack.repo CentOS-Media.repo CentOS-Vault.repo elrepo.repo
[root@dbmaster81 ~]# yum -y install drbd84-utils kmod-drbd84
[root@dbmaster81 ~]# modprobe drbd # 加載drbd模塊
[root@dbmaster81 ~]# lsmod |grep -i drbd
drbd 372759 0
libcrc32c 1246 1 drbd
安裝確認無誤后,先格式化磁盤給drbd使用,然后來看是配置:
[root@dbmaster81 ~]# fdisk /dev/sdb # 划分一個分區為sdb1,master和backup分區大小一致。
[root@dbmaster81 ~]# 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";
include "drbd.d/*.cfg";
[root@dbmaster81 ~]# cat /etc/drbd.d/drbd_basic.cfg #主要配置文件
global {
usage-count yes; # 是否參與DRBD使用者統計,默認為yes,yes or no都無所謂
}
common {
syncer { rate 30M; } # 設置主備節點同步的網絡速率最大值,默認單位是字節,我們可以設定為兆
}
resource r0 { # r0為資源名,我們在初始化磁盤的時候就可以使用資源名來初始化。
protocol C; #使用 C 協議。
handlers {
pri-on-incon-degr "echo o > /proc/sysrq-trigger ; halt -f ";
pri-lost-after-sb "echo o > /proc/sysrq-trigger ; halt -f ";
local-io-error "echo o > /proc/sysrq-trigger ; halt -f";
fence-peer "/usr/lib4/heartbeat/drbd-peer-outdater -t 5";
pri-lost "echo pri-lst. Have a look at the log file. | mail -s 'Drbd Alert' root";
split-brain "/usr/lib/drbd/notify-split-brain.sh root";
out-of-sync "/usr/lib/drbd/notify-out-of-sync.sh root";
}
net {
cram-hmac-alg "sha1";
shared-secret "MySQL-HA";
# drbd同步時使用的驗證方式和密碼信息
}
disk {
on-io-error detach;
fencing resource-only;
# 使用DOPD(drbd outdate-peer deamon)功能保證數據不同步的時候不進行切換。
}
startup {
wfc-timeout 120;
degr-wfc-timeout 120;
}
device /dev/drbd0; # 這里/dev/drbd0是用戶掛載時的設備名字,由DRBD進程創建
on dbmaster81 { #每個主機名的說明以on開頭,后面是hostname(必須在/etc/hosts可解析)
disk /dev/sdb1; # 使用這個磁盤作為drbd的磁盤/dev/drbd0。
address 172.16.22.81:7788; #設置DRBD的監聽端口,用於與另一台主機通信
meta-disk internal; # drbd的元數據存放方式
}
on dbbackup136 {
disk /dev/sdb1;
address 172.16.22.136:7788;
meta-disk internal;
}
}
[root@dbmaster81 ~]# drbdadm create-md r0 # 在/dev/sdb1分區上創建DRBD元數據庫信息,也稱元數據。
WARN:
You are using the 'drbd-peer-outdater' as fence-peer program.
If you use that mechanism the dopd heartbeat plugin program needs
to be able to call drbdsetup and drbdmeta with root privileges.
You need to fix this with these commands:
chgrp haclient /lib/drbd/drbdsetup-84
chmod o-x /lib/drbd/drbdsetup-84
chmod u+s /lib/drbd/drbdsetup-84
chgrp haclient /sbin/drbdmeta
chmod o-x /sbin/drbdmeta
chmod u+s /sbin/drbdmeta
initializing activity log
NOT initializing bitmap
Writing meta data...
New drbd meta data block successfully created. # 創建成功
success
#上面提示的命令如下,不必要執行:
useradd haclient
chgrp haclient /lib/drbd/drbdsetup-84
chmod o-x /lib/drbd/drbdsetup-84
chmod u+s /lib/drbd/drbdsetup-84
chgrp haclient /sbin/drbdmeta
chmod o-x /sbin/drbdmeta
chmod u+s /sbin/drbdmeta
[root@dbmaster81 ~]# service drbd start
[root@dbmaster81 ~]# drbdadm primary all #把當前服務器設置為primary狀態(主節點),如果這一步執行不成功,那么執行這個命令“drbdadm -- --overwrite-data-of-peer primary all”
- 如果可以正常啟動,那么就把/etc/drbd.d/drbd_basic.cfg和/etc/drbd.conf復制到backup172.16.22.136上。
- 如果不正常啟動,像下面這樣的報錯,那么就按步驟來:
[root@dbmaster81 ~]# drbdadm primary all
0: State change failed: (-2) Need access to UpToDate data # 報錯,無法設置為Primary
Command 'drbdsetup-84 primary 0' terminated with exit code 17
[root@dbmaster81 ~]# drbd-overview
0:r0/0 Connected Secondary/Secondary Inconsistent/Inconsistent
[root@dbmaster81 ~]# drbdadm primary --force r0 # 強制設置為Primary。
[root@dbmaster81 ~]# drbd-overview
0:r0/0 SyncSource Secondary/Secondary UpToDate/Inconsistent
[>....................] sync'ed: 0.1% (511600/511884)M #同步中 ,500G的磁盤,同步需要一會時間,取決於網速(交換機和網卡)
這里我就簡要說說136做的操作了,其實兩者做的操作也一樣。
- 格式化磁盤,使用配置文件指定的/dev/sdb1,兩者的容量要大小相同。
- 使用drbdadm create-md r0 創建元數據庫在/dev/sdb1。
- 啟動服務。service drbd start。
- 查看狀態。service drbd status.
在backup服務器上做完上述說的操作后,我們在bakcup服務器查看drbd的狀態:
[root@dbbackup136 ~]# service drbd status #dbbackup136上查看
drbd driver loaded OK; device status:
version: 8.4.7-1 (api:1/proto:86-101)
GIT-hash: 3a6a769340ef93b1ba2792c6461250790795db49 build by mockbuild@Build64R6, 2016-01-12 13:27:11
m:res cs ro ds p mounted fstype
0:r0 Connected Secondary/Primary UpToDate/UpToDate C #進入的主備狀態,剛開始啟動的時候會進入同步狀態,會顯示同步進度的百分比
[root@dbmaster81 ~]# service drbd status # drbd master上查看
drbd driver loaded OK; device status:
version: 8.4.7-1 (api:1/proto:86-101)
GIT-hash: 3a6a769340ef93b1ba2792c6461250790795db49 build by mockbuild@Build64R6, 2016-01-12 13:27:11
m:res cs ro ds p mounted fstype
0:r0 Connected Primary/Secondary UpToDate/UpToDate C
##進入的主備狀態
[root@dbmaster81 ~]# drbdadm dstate r0
UpToDate/UpToDate
[root@dbmaster81 ~]# drbdadm role r0
Primary/Secondary
掛載DRBD的磁盤
我們在dbmaster81(drbd master)上操作:
[root@dbmaster81 ~]# mkfs.ext4 /dev/drbd0
[root@dbmaster81 ~]# mkdir /database
[root@dbmaster81 ~]# mount /dev/drbd0 /database/
[root@dbmaster81 ~]# df -hT
Filesystem Type Size Used Avail Use% Mounted on
/dev/sda2 ext4 28G 2.8G 24G 11% /
tmpfs tmpfs 238M 0 238M 0% /dev/shm
/dev/sda1 ext4 283M 57M 212M 22% /boot
/dev/drbd0 ext4 11G 26M 9.6G 1% /database #g掛載成功
主端掛載完后去格式化備端和掛載,主要是檢測備端是否能夠正常掛載和使用,格式化之前需要主備狀態切換,切換的方法請看下面的DRBD設備角色切換的內容。下面就在備端格式化和掛載磁盤。
[root@dbbackup136 ~]# drbdadm primary r0
[root@dbbackup136 ~]# service drbd status
drbd driver loaded OK; device status:
version: 8.4.7-1 (api:1/proto:86-101)
GIT-hash: 3a6a769340ef93b1ba2792c6461250790795db49 build by mockbuild@Build64R6, 2016-01-12 13:27:11
m:res cs ro ds p mounted fstype
0:r0 Connected Primary/Secondary UpToDate/UpToDate C # 確保是Primary狀態才可以格式化掛載使用。主要是
[root@dbbackup136 ~]# mkfs.ext4 /dev/drbd0
備端也可以這樣掛載磁盤,但是掛載的前提是備端切換成master端。只有master端可以掛載磁盤。
問題經驗總結
這里說說我當初遇到的一個問題:
drbd在一次使用LVM的時候,使用的是500M的邏輯卷,然后在Primary格式化掛載,發現是500M的容量后,就刪除500M的邏輯卷通過lvremove命令。於是重新分了500G的邏輯卷,drbd同步元數據后,直接掛載在mysql數據目錄下,通過df命令發現還是drbd0的大小還是500M的,找了半天的原因,最后發現,原來在使用新邏輯卷500G的時候,沒有mkfs.ext4格式化磁盤就掛載在mysql數據目錄下導致的。 解決方法就是重新格式化drbd0磁盤后掛載就可以使用500G的容量了
DRBD設備角色切換
DRBD設備在角色切換之前,需要在主節點執行umount命令卸載磁盤先,然后再把一台主機上的DRBD角色修改為Primary,最后把當前節點的磁盤掛載
第一種方法:
在172.16.22.81上操作(當前是primary)。
[root@dbmaster81 ~]# umount /database/
[root@dbmaster81 ~]# drbdadm secondary r0
[root@dbmaster81 ~]# service drbd status
drbd driver loaded OK; device status:
version: 8.4.7-1 (api:1/proto:86-101)
GIT-hash: 3a6a769340ef93b1ba2792c6461250790795db49 build by mockbuild@Build64R6, 2016-01-12 13:27:11
m:res cs ro ds p mounted fstype
0:r0 Connected Secondary/Secondary UpToDate/UpToDate C #狀態已經轉變了
在172.16.22.136上操作。
[root@dbbackup136 ~]# drbdadm primary r0
WARN:
You are using the 'drbd-peer-outdater' as fence-peer program.
If you use that mechanism the dopd heartbeat plugin program needs
to be able to call drbdsetup and drbdmeta with root privileges.
You need to fix this with these commands:
chgrp haclient /lib/drbd/drbdsetup-84
chmod o-x /lib/drbd/drbdsetup-84
chmod u+s /lib/drbd/drbdsetup-84
chgrp haclient /sbin/drbdmeta
chmod o-x /sbin/drbdmeta
chmod u+s /sbin/drbdmeta
[root@dbbackup136 ~]# service drbd status
drbd driver loaded OK; device status:
version: 8.4.7-1 (api:1/proto:86-101)
GIT-hash: 3a6a769340ef93b1ba2792c6461250790795db49 build by mockbuild@Build64R6, 2016-01-12 13:27:11
m:res cs ro ds p mounted fstype
0:r0 Connected Primary/Secondary UpToDate/UpToDate C #狀態已經轉變了
[root@dbbackup136 ~]# mkfs.ext4 /dev/drbd0 # 在沒有切換成primary狀態的時候,是沒法格式化磁盤的。
第二種方法:
在172.16.22.136上操作(當前是primary)。
[root@dbbackup136 ~]# service drbd status
drbd driver loaded OK; device status:
version: 8.4.7-1 (api:1/proto:86-101)
GIT-hash: 3a6a769340ef93b1ba2792c6461250790795db49 build by mockbuild@Build64R6, 2016-01-12 13:27:11
m:res cs ro ds p mounted fstype
0:r0 Connected Primary/Secondary UpToDate/UpToDate C /database ext4
[root@dbbackup136 ~]# service drbd stop # 先停止服務
Stopping all DRBD resources:
在172.16.22.81上操作
[root@dbmaster81 ~]# drbdadm -- --overwrite-data-of-peer primary all #強行切換為primary
[root@dbmaster81 ~]# service drbd status
drbd driver loaded OK; device status:
version: 8.4.7-1 (api:1/proto:86-101)
GIT-hash: 3a6a769340ef93b1ba2792c6461250790795db49 build by mockbuild@Build64R6, 2016-01-12 13:27:11
m:res cs ro ds p mounted fstype
0:r0 WFConnection Primary/Unknown UpToDate/Outdated C # 切換成功
DRBD的性能優化
1. 網絡環境
使用千兆或多張千兆網卡綁定的網絡接口,交換機也必須是千兆級別的,且數據同步網絡需要和業務網絡隔開,避免兩者相互干擾。
2. 磁盤性能
給DRBD做磁盤分區的硬盤性能盡量好點,可以考慮轉速15K/Min的SAS硬盤或者SSD,或者使用RAID5 或者RAID 0等,在網絡環境很好的情況下,DRBD分區可能由於I/O的寫性能成為瓶頸。
3. 更新系統
盡量把系統更新成最新的內容,同時使用最新的DRBD,目前kernel2.6.13已經准備把DRBD作為Linux Kernel的主干分支了。
4. syncer的參數
syncer主要用來設置同步相關參數,可以設置“重新”同步(re-synchronization)的速率,當節點間出現不一致的block時,DRBD就需要執行re-synchronization動作,而syncer中的參數rate就是設置同步速率的,rate設置與網絡和磁盤IO能力密切相關。
對於這個rate值的設定,官方建議是同步速率和磁盤寫入速率中最小者的30%帶寬來設置re-synchronization是比較合適。
例如:網絡是千兆的(速率為125MB/S),磁盤寫入速度(110MB/S),那么rate應該設置為33MB(110*30%=33MB)。這樣設置的原因是因為:DRBD同步由兩個不同的進程來負責,一個replication進程用來同步block的更新,這個值受限於參數;一個synchronization進程來同步元數據信息,這個值不收參數設置限制。。如果寫入量非常大,設置的參數超過了磁盤的寫入性能,那么元數據同步就會收到干擾,傳輸速度變慢,導致機器負載很高,性能下降的很厲害,所這個這個rate值要根據實際環境設置,如果設置過大,就會把所有的帶寬占滿,導致replication進程沒有帶寬可用,最終導致I/O停止,出現同步不正常的現象。
5. al-extents 參數設置
al-extents控制着一次向磁盤寫入多少個4MB的數據塊。增大這個參數的值有以下幾個好處:
- 可以減少更新元數據到DRBD設備的頻率。
- 降低同步數據時對I/O流中斷數量。
- 提高修改DRBD設備的速度。
但是也有一個風險,當主節點宕機以后,所有活動的數據(al-extends的值*4M的數據庫)需要在同步連接建立后重新同步,即在主節點出現宕機時,備用節點出現數據不一致的情況。所以不建議在HA部署上調整這個參數。可以在極個別情況下根據需求調整。
更多內容請參考官網地址:http://www.drbd.org/en/doc/users-guide-84/ch-admin#s-check-status
