┌─────────────────────────────────────┐
│ Application / VIP (192.168.0.253) │ ← Heartbeat 管理 IP 漂移
├─────────────────────────────────────┤
│ MySQL Service (mysqld) │ ← Heartbeat 管理服務啟停
├─────────────────────────────────────┤
│ Filesystem (ext3/ext4 on /dev/drbd0)│ ← Heartbeat 管理掛載/卸載
├─────────────────────────────────────┤
│ DRBD Block Device (/dev/drbd0) │ ← DRBD 同步鏡像 /dev/sdb1
├─────────────────────────────────────┤
│ Physical Disk (/dev/sdb1) │ ← 兩節點同規格分區
└─────────────────────────────────────┘
資源啟動順序 (左→右):DRBD Primary → 掛載 FS → 啟動 MySQL → 綁定 VIP
資源停止順序 (右←左):釋放 VIP → 停止 MySQL → 卸載 FS → DRBD Secondary
| 節點 | 主機名 | 管理 IP (eth0) | 心跳/同步 IP (eth1) | 角色 |
|---|---|---|---|---|
| Node 1 | ha1 | 192.168.0.251 | 192.168.254.4 | Primary (偏好) |
| Node 2 | ha2 | 192.168.0.252 | 192.168.254.5 | Secondary |
/dev/sdb1 (雙機同大小,無檔案系統)192.168.0.253/24 綁定 eth0:0# 兩節點同步執行
yum -y install drbd82 kmod-drbd82
yum -y install heartbeat heartbeat-pils heartbeat-stonith
yum -y install mysql mysql-server
# 載入模組
modprobe drbd
lsmod | grep drbd
global { usage-count yes; }
common { syncer { rate 10M; } } # 百兆網卡 10M,千兆 100M
resource r0 {
protocol C;
net {
cram-hmac-alg sha1;
shared-secret "FooFunFactory";
}
on ha1 {
device /dev/drbd0;
disk /dev/sdb1;
address 192.168.254.4:7898;
meta-disk internal;
}
on ha2 {
device /dev/drbd0;
disk /dev/sdb1;
address 192.168.254.5:7898;
meta-disk internal;
}
}
# 兩節點執行
drbdadm create-md r0
# 輸入 yes 確認
# 啟動 (ha1 先啟動等待,ha2 啟動後自動握手同步)
/etc/init.d/drbd start
# 觀察同步
cat /proc/drbd
# 等待 ds:UpToDate/UpToDate
# ha1 提升 Primary (首次需 --force)
drbdsetup /dev/drbd0 primary -o
# 建立檔案系統 (僅 Primary)
mkfs.ext3 /dev/drbd0
mount /dev/drbd0 /mnt
touch /mnt/huzi
ls /mnt/ # 驗證寫入
# 降級測試
umount /mnt
drbdadm secondary r0
# ha2 提升
drbdadm primary r0
mount /dev/drbd0 /mnt
ls /mnt/ # 應看到 huzi
# 在 ha1 (Primary) 執行
service mysqld start # 初始化系統表
service mysqld stop
mount /dev/drbd0 /mnt
cp -ar /var/lib/mysql/* /mnt/
umount /mnt
# 修改 my.cnf
datadir = /var/lib/mysql # 掛載點即為此
socket = /var/lib/mysql/mysql.sock
/etc/ha.d/ha.cf:
debugfile /var/log/ha-debug
logfile /var/log/ha-log
logfacility local0
keepalive 2
deadtime 10
warntime 5
initdead 120
ucast eth1 192.168.254.5 # 對端心跳 IP
auto_failback on
watchdog /dev/watchdog
node ha1
node ha2
ping 192.168.254.1 # 網關偵測
respawn hacluster /usr/lib/heartbeat/ipfail
apiauth ipfail gid=haclient uid=hacluster
/etc/ha.d/authkeys (chmod 600):
auth 1
1 crc
/etc/ha.d/haresources:
ha1 IPaddr::192.168.0.253/24/eth0:1 mysqld_umount mysqld
自定義資源腳本 /etc/ha.d/resource.d/mysqld_umount:
#!/bin/sh
# DRBD + FS + MySQL 整合啟停腳本
. /etc/ha.d/shellfuncs
case "$1" in
start)
/sbin/drbdadm primary all
/bin/mount /dev/drbd0 /var/lib/mysql
;;
stop)
/bin/umount /var/lib/mysql
/sbin/drbdadm secondary all
;;
*) echo "Usage: $0 {start|stop}"; exit 1 ;;
esac
exit 0
chmod +x /etc/ha.d/resource.d/mysqld_umount
# ha1 複製至 ha2
scp -r /etc/ha.d ha2:/etc/
# ha2 修改 ha.cf 的 ucast 指向 ha1
# 兩節點同時啟動
/etc/init.d/heartbeat start
# 觀察日誌
tail -f /var/log/ha-log
# 關鍵成功標誌:
# "Local Resource acquisition completed"
# "Initial resource acquisition complete (auto_failback)"
# ip addr show eth0:0 顯示 VIP
# mount | grep drbd0
# cat /proc/drbd 顯示 Primary/Secondary
| 測試場景 | 操作 | 觀察結果 | 切換時間 |
|---|---|---|---|
| 手動待機 | Primary 執行 /usr/lib/heartbeat/hb_standby | 資源順序釋放 → Secondary 獲取 → VIP/FS/MySQL 全部遷移 | ~10 秒 |
| 網路中斷 | 拔掉 Primary eth1 (心跳網卡) | deadtime 後判定失聯,切換流程同手動 | deadtime + ~10 秒 |
| 主機關機 | Primary shutdown -h now | 同網路中斷 | 同網路中斷 |
| 主機斷電 | 物理斷電 | 同關機,DRBD 保證資料一致性 | 同關機 |
驗證結果:4 次測試中 3 次資料零差異,1 次相差 1 條 (極邊界競態),整體符合生產可用性要求。
rate 設為網卡 70-80%,避免擠佔業務流量innodb_flush_log_at_trx_commit=1、sync_binlog=1、innodb_buffer_pool_size 留 20% 系統/DRBDdrbdadm status、crm_mon -1、VIP 存活、MySQL 連線/延遲/錯誤率、磁碟/網路飽和度| 維度 | DRBD + Heartbeat | 主從複制 (非同步/半同步) |
|---|---|---|
| 資料一致性 | 強一致 (Protocol C),零資料丟失 | 非同步可能丟失、半同步仍有極小窗口 |
| 讀擴展 | Secondary 不可讀 (單主) | Slave 可讀,支援讀寫分離 |
| 切換速度 | ~10-30 秒 | 秒級 (MHA/Orchestrator) 至分鐘級 |
| 架構複雜度 | 中 (雙機、共享塊裝置) | 低 (多 Slave、邏輯複制) |
| 跨機房 | 延遲敏感,通常同城 | 天然支援跨地域非同步 |
| 成本 | 雙機專用儲存 | 可用商品硬體、雲盤 |
組合最佳實踐:DRBD 雙機保核心庫強一致 HA + 額外掛 1-2 個非同步 Slave 承擔讀流量/備份/異地災備。