首页 > 数据库 > MySQL > MySQL5.7+Keepalived双主HA架构
数据库架构:双主复制
master:192.168.8.57
slave1:192.168.8.58
keepalived工具包
keepalived-1.4.5.tar.gz
一、添加非本机IP绑定支持
一、添加非本机IP绑定支持
echo
"net.ipv4.ip_nonlocal_bind=1"
>>
/etc/sysctl
.conf
sysctl -p
|
二、下载并安装 keepalived
tar
zxvf keepalived-1.4.5.
tar
.gz
cd
keepalived-1.4.5
.
/configure
--prefix=
/usr/local/keepalived/
make
&&
make
install
keepalived 开机自动启动
systemctl
enable
keepalived
|
三、配置keepalived
192.168.8.57
# vi /etc/keepalived/keepalived.conf
! Configuration
file
for
keepalived
global_defs {
router_id 8.57
notification_email {
zdd5503@163.com
}
notification_email_from zdd5503@163.com
smtp_server stmp.163.com
smtp_connect_timeout 30
}
vrrp_script chk_mysql {
script
"/etc/keepalived/check_mysql.sh"
interval 3
}
vrrp_instance V_mysql_1 {
state BACKUP
interface enp0s3
virtual_router_id 200
priority 100
advert_int 1
nopreempt
authentication {
auth_type PASS
auth_pass steven
}
track_script {
chk_mysql
}
virtual_ipaddress {
192.168.8.88
/24
}
}
|
192.168.8.58
! Configuration
file
for
keepalived
global_defs {
router_id 8.58
notification_email {
zdd5503@163.com
}
notification_email_from zdd5503@163.com
smtp_server stmp.163.com
smtp_connect_timeout 30
}
vrrp_instance V_mysql_1 {
state BACKUP
interface enp0s3
virtual_router_id 200
priority 90
advert_int 1
authentication {
auth_type PASS
auth_pass steven
}
notify_master
/etc/keepalived/notify_master_mysql
.sh
virtual_ipaddress {
192.168.8.88
/24
}
}
|
check_mysql.sh
#!/bin/bash
#/etc/keepalived/check_mysql.sh
#chmod u+x /etc/keepalived/check_mysql.sh
if
[ `
ps
-ef|
grep
-w
"$0"
|
grep
"/bin/sh*"
|
grep
"?"
|
grep
"?"
|
grep
-
v
"grep"
|
wc
-l` -gt 2 ];
then
#
exit
fi
mysql_con=
'/usr/local/mysql/bin/mysql -uroot -pmysql'
function
excute_query {
$mysql_con -e
"select 1 from dual;"
2>>
/mysql/log/check_mysql
.err
}
function
service_error {
echo
-e
"`date "
+%F %H:%M:%S
"` -----mysql service error,now stop keepalived-----"
>>
/mysql/log/check_mysql
.err
/sbin/service
keepalived stop &>>
/mysql/log/check_mysql
.err
echo
-e
"\n@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"
>>
/mysql/log/check_mysql
.err
}
function
query_error {
echo
-e
"`date "
+%F %H:%M:%S
"` -----query error, but mysql service ok, retry after 30s-----"
>>
/mysql/log/check_mysql
.err
sleep
30
excute_query
if
[ $? -
ne
0 ];
then
echo
-e
"`date "
+%F %H:%M:%S
"` -----still can't execute query-----"
>>
/mysql/log/check_mysql
.err
echo
-e
"`date "
+%F %H:%M:%S
"` -----set read_only = 1 on DB1-----"
>>
/mysql/log/check_mysql
.err
$mysql_con -e
"set global read_only = 1;"
2>>
/mysql/log/check_mysql
.err
echo
-e
"`date "
+%F %H:%M:%S
"` -----kill current client thread-----"
>>
/mysql/log/check_mysql
.err
rm
-f
/mysql/log/kill
.sql &>
/dev/null
$mysql_con -NB -e
'select concat("kill ",id,";") from information_schema.PROCESSLIST where command="Query" or command="Execute"'
>
/mysql/log/kill
.sql
$mysql_con -e
"source /mysql/log/kill.sql"
sleep
2
echo
-e
"`date "
+%F %H:%M:%S
"` -----stop keepalived-----"
>>
/mysql/log/check_mysql
.err
systemctl stop keepalived &>>
/mysql/log/check_mysql
.err
echo
-e
"\n@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"
>>
/mysql/log/check_mysql
.err
else
echo
-e
"`date "
+%F %H:%M:%S
"` -----query ok after 30s-----"
>>
/mysql/log/check_mysql
.err
echo
-e
"\n@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"
>>
/mysql/log/check_mysql
.err
fi
}
excute_query
if
[ $? -
ne
0 ];
then
service mysql status &>
/dev/null
if
[ $? -
ne
0 ];
then
service_error
else
query_error
fi
fi
|
notify_master_mysql.sh
#!/bin/bash
#/etc/keepalived/notify_master_mysql.sh
#chmod u+x /etc/keepalived/notify_master_mysql.sh
change_log=
/mysql/log/state_change
.log
slave_status_log=
/mysql/log/slave_status_log
.log
mysql_conn=
'/usr/local/mysql/bin/mysql -uroot -pmysql'
echo
-e
"`date "
+%F %H:%M:%S
"` -----keepalived change to MASTER-----"
>> $change_log
echo
-e
"`date "
+%F %H:%M:%S
"` ----------"
>> $slave_status_log
$mysql_conn -e
"show slave status\G;"
>> $slave_status_log
Slave_IO_Running=`$mysql_conn -e
"show slave status\G;"
|
egrep
-w
"Slave_IO_Running|Slave_SQL_Running"
|
awk
'NR==1{print}'
|
awk
'{print $2}'
`
Slave_SQL_Running=`$mysql_conn -e
"show slave status\G;"
|
egrep
-w
"Slave_IO_Running|Slave_SQL_Running"
|
awk
'NR==2{print}'
|
awk
'{print $2}'
`
Master_Log_File=`$mysql_conn -e
"show slave status\G;"
|
egrep
-w
"Master_Log_File|Read_Master_Log_Pos|Exec_Master_Log_Pos"
|
awk
'NR==1{print}'
|
awk
'{print $2}'
`
Read_Master_Log_Pos=`$mysql_conn -e
"show slave status\G;"
|
egrep
-w
"Master_Log_File|Read_Master_Log_Pos|Exec_Master_Log_Pos"
|
awk
'NR==2{print}'
|
awk
'{print $2}'
`
Exec_Master_Log_Pos=`$mysql_conn -e
"show slave status\G;"
|
egrep
-w
"Master_Log_File|Read_Master_Log_Pos|Exec_Master_Log_Pos"
|
awk
'NR==3{print}'
|
awk
'{print $2}'
`
action() {
echo
-e
"`date "
+%F %H:%M:%S
"` -----set read_only = 0 on itpuxdb2-slave-----"
>> $change_log
$mysql_conn -e
"set global read_only = 0;"
2>> $change_log
$mysql_conn -e
"stop slave;"
2>> $change_log
echo
"slave1 keepalived转为MASTER状态,线上数据库切换至slave1"
|
/bin/mailx
-s
"slave1 keepalived change to MASTER"
\
zdd5503@163.com 2>> $change_log
echo
-e
"@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n"
>> $change_log
}
if
[
"$Slave_IO_Running"
=
"Yes"
-a
"$Slave_SQL_Running"
=
"Yes"
];
then
if
[ $Read_Master_Log_Pos = $Exec_Master_Log_Pos ];
then
echo
-e
"`date "
+%F %H:%M:%S
"` -----Master_Log_File=$Master_Log_File . Exec_Master_Log_Pos($Exec_Master_Log_Pos) is equal Read_Master_Log_Pos($Read_Master_Log_Pos)"
>> $change_log
action
$mysql_conn -e
"reset slave all;"
2>> $change_log
else
echo
-e
"`date "
+%F %H:%M:%S
"` -----Master_Log_File=$Master_Log_File . Exec_Master_Log_Pos($Exec_Master_Log_Pos) is behind Read_Master_Log_Pos($Read_Master_Log_Pos), The waits time is more than 10s,now force change."
>> $change_log
sleep
10
action
$mysql_conn -e
"reset slave all;"
2>> $change_log
exit
fi
action
else
echo
-e
"itpuxdb2-slave's slave status is wrong,now force change. Master_Log_File=$Master_Log_File Read_Master_Log_Pos=$Read_Master_Log_Pos Exec_Master_Log_Pos=$Exec_Master_Log_Pos"
>> $change_log
action
fi
|
四、启动 keepalived
systemctl daemon-reload
systemctl
enable
keepalived
systemctl stop keepalived
systemctl start keepalived
|
查看keepalived进程
ps
-ef|
grep
keepalived
root 7406 1 0 20:25 ? 00:00:00
/usr/local/keepalived/sbin/keepalived
-D -d -S 0
root 7407 7406 0 20:25 ? 00:00:00
/usr/local/keepalived/sbin/keepalived
-D -d -S 0
root 7408 7406 0 20:25 ? 00:00:00
/usr/local/keepalived/sbin/keepalived
-D -d -S 0
root 7412 3067 0 20:25 pts
/2
00:00:00
grep
--color=auto keepalived
|
看到这样的说明启动成功,否则启动失败
五、查看VIP状态
192.168.8.57
ip a |
grep
88
inet 192.168.8.88
/24
scope global secondary enp0s3
|
192.168.8.58则查询不到
六、通过VIP连接MySQL
mysql -uroot -pmysql -h192.168.8.88 -e
"select @@hostname;"
mysql: [Warning] Using a password on the
command
line interface can be insecure.
+------------+
| @@
hostname
|
+------------+
| master |
+------------+
|
七、模拟宕机
关闭192.168.8.57服务器
mysql -uroot -pmysql -h192.168.8.88 -e
"select @@hostname;"
mysql: [Warning] Using a password on the
command
line interface can be insecure.
+------------+
| @@
hostname
|
+------------+
| slave1 |
+------------+
|
MySQL连接切换成功,业务可正常切换至备机
八、故障恢复
192.168.8.57恢复之后,重新将该节点数据库加入至双主复制
reset slave;
change master
to
master_host=
'192.168.8.58'
,
master_port=3306,
master_user=
'repl'
,
master_password=
'mysql'
,
master_auto_position=1;
start slave;
|
等数据追平之后,可以将vip切换至192.168.8.57
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/31429259/viewspace-2218198/,如需转载,请注明出处,否则将追究法律责任。