標籤:
Keepalived MySQL故障自動切換指令碼
MySQL架構為master-slave(主從),master故障自動切換到slave上。當然也可以設定為雙master,但這裡有個弊端:就是當主的壓力很大時,從上延時很大,比如落後2000秒,此時主掛了,從接管(VIP漂移到從),使用者剛才發表的文章,此時因為同步延時大,還沒複製過來,於是使用者又發表了一篇文章,當原來的master修好後,因從的IO和SQL線程還在開啟狀態,還會繼續同步剛才沒有同步複製完的資料,這時有可能把使用者新發表的文章更改掉,造成使用者資料丟失。
考慮到這種情況,我這裡還是用的master-slave(主從)架構。
keepalive安裝很簡單,這裡不再囉嗦。主要看下設定檔和指令碼:
# more /etc/keepalived/keepalived.conf
global_defs {
router_id KeepAlive_Mysql
}
vrrp_script check_run {
script "/root/sh/mysql_check.sh"
interval 300
}
vrrp_sync_group VG1 {
group {
VI_1
}
}
vrrp_instance VI_1 {
state BACKUP
interface eth0
virtual_router_id 51
priority 100
advert_int 1
nopreempt
authentication {
auth_type PASS
auth_pass 1111
}
track_script {
check_run
}
notify_master /root/sh/master.sh
notify_backup /root/sh/backup.sh
notify_stop /root/sh/stop.sh
virtual_ipaddress {
192.168.8.150
}
}
notify_master <STRING>|<QUOTED-STRING> # 狀態改變為MASTER後執行的指令碼notify_backup <STRING>|<QUOTED-STRING> # 狀態改變為BACKUP後執行的指令碼notify_fault <STRING>|<QUOTED-STRING> # 狀態改變為FAULT後執行的指令碼notify_stop <STRING>|<QUOTED-STRING> # VRRP停止後後執行的指令碼notify <STRING>|<QUOTED-STRING> # (1)任意狀態改變後執行的指令碼
下面解釋下這4個指令碼的用法:
mysql_check.sh(健全狀態檢查指令碼,當發現mysql串連不上,會把keepalive進程關閉,並切換。)
# more mysql_check.sh
#!/bin/bash
. /root/.bash_profile
count=1
while true
do
mysql -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
exit 0
else
if [ $i = 1 ] && [ $j = 0 ]
then
exit 0
else
if [ $count -gt 5 ]
then
break
fi
let count++
continue
fi
fi
done
/etc/init.d/keepalived stop
master.sh(狀態改變為MASTER後執行的指令碼) (首先判斷同步複製是否執行完畢,如果未執行完畢,等1分鐘後,不論是否執行完畢,都跳過,並停止同步複製進程。) (其次,更改前端程式串連的業務帳號admin的許可權和密碼,並記錄當前切換以後的日誌和POS點。)
# more master.sh
#!/bin/bash
. /root/.bash_profile
Master_Log_File=$(mysql -e "show slave status\G" | grep -w Master_Log_File | awk -F": " ‘{print $2}‘)
Relay_Master_Log_File=$(mysql -e "show slave status\G" | grep -w Relay_Master_Log_File | awk -F": " ‘{print $2}‘)
Read_Master_Log_Pos=$(mysql -e "show slave status\G" | grep -w Read_Master_Log_Pos | awk -F": " ‘{print $2}‘)
Exec_Master_Log_Pos=$(mysql -e "show slave status\G" | grep -w Exec_Master_Log_Pos | awk -F": " ‘{print $2}‘)
i=1
while true
do
if [ $Master_Log_File = $Relay_Master_Log_File ] && [ $Read_Master_Log_Pos -eq $Exec_Master_Log_Pos ]
then
echo "ok"
break
else
sleep 1
if [ $i -gt 60 ]
then
break
fi
continue
let i++
fi
done
mysql -e "stop slave;"
mysql -e "flush logs;GRANT ALL PRIVILEGES ON *.* TO ‘admin‘@‘%‘ IDENTIFIED BY ‘admin‘;flush privileges;"
mysql -e "show master status;" > /tmp/master_status_$(date "+%y%m%d-%H%M").txt
backup.sh(狀態改變為BACKUP後執行的指令碼)
# more backup.sh
#!/bin/bash
. /root/.bash_profile
mysql -e "GRANT ALL PRIVILEGES ON *.* TO ‘admin‘@‘%‘ IDENTIFIED BY ‘1q2w3e4r‘;flush privileges;"
stop.sh(keepalived停止後後執行的指令碼) (首先把admin密碼更改掉) (其次,設定參數,保證不遺失資料) (最後,查看是否還有寫操作,不論是否執行完畢,1分鐘後都退出。)
# more stop.sh
#!/bin/bash
. /root/.bash_profile
mysql -e "GRANT ALL PRIVILEGES ON *.* TO ‘admin‘@‘%‘ IDENTIFIED BY ‘1q2w3e4r‘;flush privileges;"
mysql -e "set global innodb_support_xa=1;"
mysql -e "set global sync_binlog=1;"
mysql -e "set global innodb_flush_log_at_trx_commit=1;"
M_File1=$(mysql -e "show master status\G" | awk -F‘: ‘ ‘/File/{print $2}‘)
M_Position1=$(mysql -e "show master status\G" | awk -F‘: ‘ ‘/Position/{print $2}‘)
sleep 1
M_File2=$(mysql -e "show master status\G" | awk -F‘: ‘ ‘/File/{print $2}‘)
M_Position2=$(mysql -e "show master status\G" | awk -F‘: ‘ ‘/Position/{print $2}‘)
i=1
while true
do
if [ $M_File1 = $M_File2 ] && [ $M_Position1 -eq $M_Position2 ]
then
echo "ok"
break
else
sleep 1
if [ $i -gt 60 ]
then
break
fi
continue
let i++
fi
done
mysql+keepalived主從切換指令碼 轉