需求:想要实现当MySQL服务挂了之后,能够自动切换到另一台,不对当前服务造成过多影响。查找了很多实现数据库高可用方案,比较常见的有MHA(至少三台,一主多从)、开源数据库中间件(Mycat)等,最终选取了一个配置相对简单一些的双主MySQL集群+Keepalived方案。准备了两台虚拟机172.30.24.97、172.30.24.98,已安装好10.6.8-MariaDB MariaDB Server。
1、MySQL双主搭建
可参考上一篇文章:MySQL主从数据库简单搭建
双主也可以理解为互为主从,此处仅简单记录一下步骤。
1.1 修改配置文件
172.30.24.97数据库配置文件my.cnf
添加部分如下:
[mysqld]
server-id=1
binlog_format=ROW #指定mysql的binlog日志的格式
log-bin=mysql-bin #开启二进制日志
auto-increment-increment = 2 #字段变化增量值
auto-increment-offset = 1 #初始字段ID为1
slave-skip-errors = all #忽略所有复制产生的错误
172.30.24.98数据库配置文件my.cnf
添加部分如下:
[mysqld]
server-id=2
binlog_format=ROW #指定mysql的binlog日志的格式
log-bin=mysql-bin #开启二进制日志
auto-increment-increment = 2 #字段变化增量值
auto-increment-offset = 2 #初始字段ID为2
slave-skip-errors = all #忽略所有复制产生的错误
1.2 创建复制用户并授权
两个MySQL数据库都需要执行
grant replication slave on *.* to 'rep'@'%' identified by '123456';
部分配置项解释:
两台数据库配置只有server-id不同和auto-increment-offset不同,其他需要相同。
auto-increment-increment=2:表示自增长字段每次递增的量,其默认值是1。它的值应设为整个结构中服务器的总数,示例用到两台服务器,所以值设为2。
auto-increment-offset=2:用来设定数据库中自动增长的起点(即初始值),因为这两能服务器都设定了一次自动增长值2,所以它们的起点必须得不同,这样才能避免两台服务器数据同步时出现主键冲突。
1.3 保持数据一致
示例中172.30.24.97已经运行了一些数据,172.30.24.98是新的数据库,需要手动将172.30.24.97的数据拷贝到172.30.24.98,并应用。因为开启双主不会自动同步未配置前的数据,只会同步配置之后的数据库操作。
在172.30.24.98上进入到数据库bin目录下执行
# 导出数据
./mysqldump -uroot -p123456 -P3310 -h 172.30.24.97 --single-transaction --all-databases --master-data=2 > host97.sql
# 导入数据
./mysql -uroot -pUmcDp1234 -P3310 < host97.sql
1.4 开启复制
172.30.24.98上开启复制,以下脚本在172.30.24.98上执行
CHANGE MASTER TO MASTER_HOST='172.30.24.97', MASTER_PORT=3310, MASTER_USER='rep', MASTER_PASSWORD='123456', MASTER_LOG_FILE='mysql-bin.000001', MASTER_LOG_POS=328;
START SLAVE;
show slave status \G
172.30.24.97上开启复制,以下脚本在172.30.24.97上执行
CHANGE MASTER TO MASTER_HOST='172.30.24.98', MASTER_PORT=3310, MASTER_USER='rep', MASTER_PASSWORD='123456', MASTER_LOG_FILE='mysql-bin.000001', MASTER_LOG_POS=4829028;
START SLAVE;
show slave status \G
1.5 测试双主复制
在172.30.24.98数据库中插入数据,查看172.30.24.97上是否同步
在172.30.24.97数据库中插入数据,查看172.30.24.98上是否同步
2、Keepalived配置启动
2.1 安装
Keepalived下载:Keepalived下载
安装方式有两种
1、yum安装
2、源码包安装
示例使用的是源码包安装,版本是 Version 2.2.8 。
将下载的源码包上传至服务器
# 解压
tar -zxvf keepalived-2.2.8.tar.gz
# 编译
cd keepalived-2.2.8/
# --prefix 指定安装地址
./configure --prefix=/usr/local/keepalived/
# 编译并安装
make && make install
指定安装地址可能会报缺少依赖(gcc、OpenSSL),如果有问题需要手动安装一下依赖。
报错示例:
执行安装依赖:
yum install gcc
yum install openssl-devel
2.2 创建配置文件
# 创建keepalived配置文件目录
mkdir /etc/keepalived
# 拷贝 配置文件 到/etc/keepalived目录下
cp /usr/local/keepalived/etc/keepalived/keepalived.conf /etc/keepalived/
# 复制keepalived脚本到/etc/init.d/ 目录 (就可以使用 service 命令便捷调用)
cp /usr/local/keepalived/etc/rc.d/init.d/keepalived /etc/init.d/
2.3 修改配置文件
示例使用172.30.24.97作为主,172.30.24.98作为子,172.30.24.96为虚拟出的ip。
172.30.24.97的keepalived配置文件如下:
! Configuration File for keepalived
# 全局配置
global_defs {
# 路由标志
router_id LVS_DEVEL
}
# 集群资源监控
vrrp_script chk_mysql_port { # 检测mysql服务是否在运行。有很多方式,比如进程,用脚本检测等等
script "/root/chk_mysql.sh" # 这里通过脚本监测
interval 2 # 脚本执行间隔,每2s检测一次
weight -5 # 脚本结果导致的优先级变更,检测失败(脚本返回非0)则优先级 -5
fall 2 # 检测连续2次失败才算确定是真失败。会用weight减少优先级(1-255之间)
rise 1 # 检测1次成功就算成功。但不修改优先级
}
vrrp_instance VI_1 {
state MASTER # 设置的当前主机为主节点,如果是备用节点,则设置为BACKUP
interface ens3 # 主机网卡 可以用ifconfig查看来决定设置哪一个
mcast_src_ip 172.30.24.97 # 主机ip
virtual_router_id 35 # 路由器标识,MASTER和BACKUP必须是一致的
priority 101 # 定义优先级,数字越大,优先级越高,在同一个vrrp_instance下,MASTER的优先级必须大于BACKUP的优先级。这样MASTER故障恢复后,就可以将VIP资源再次抢回来
advert_int 1 # 设置VRRP Advertisement(通告)消息的发送间隔为"1"秒
authentication { # 设置VRRP的认证信息,用于确保只有经过认证的路由器才能参与VRRP组。
auth_type PASS # 指定认证类型为"PASS",表示使用密码进行认证
auth_pass 1111 # 设置密码为"1111",用于进行认证
}
# 设置虚拟IP地址,当keepalived状态切换为MASTER时,此IP会自动添加到系统中
# 当状态切换到BACKUP时,此IP会自动从系统中删除
# 可以通过命令ip addr查看切换后的状态
virtual_ipaddress {
# 虚拟IP地址
172.30.24.96
}
# 集群资源监控,组合vrrp-script进行
track_script {
chk_mysql_port
}
}
172.30.24.98的keepalived配置文件可以复制172.30.24.97的同时修改部分配置。
172.30.24.98的keepalived配置文件如下:
! Configuration File for keepalived
# 全局配置
global_defs {
# 路由标志
router_id LVS_DEVEL
}
# 集群资源监控
vrrp_script chk_mysql_port { # 检测mysql服务是否在运行。有很多方式,比如进程,用脚本检测等等
script "/root/chk_mysql.sh" # 这里通过脚本监测
interval 2 # 脚本执行间隔,每2s检测一次
weight -5 # 脚本结果导致的优先级变更,检测失败(脚本返回非0)则优先级 -5
fall 2 # 检测连续2次失败才算确定是真失败。会用weight减少优先级(1-255之间)
rise 1 # 检测1次成功就算成功。但不修改优先级
}
vrrp_instance VI_1 {
state BACKUP # 设置的当前主机为主节点,如果是备用节点,则设置为BACKUP
interface ens3 # 主机网卡 可以用ifconfig查看来决定设置哪一个
mcast_src_ip 172.30.24.98 # 主机ip
virtual_router_id 35 # 路由器标识,MASTER和BACKUP必须是一致的
priority 99 # 定义优先级,数字越大,优先级越高,在同一个vrrp_instance下,MASTER的优先级必须大于BACKUP的优先级。这样MASTER故障恢复后,就可以将VIP资源再次抢回来
advert_int 1 # 设置VRRP Advertisement(通告)消息的发送间隔为"1"秒
authentication { # 设置VRRP的认证信息,用于确保只有经过认证的路由器才能参与VRRP组。
auth_type PASS # 指定认证类型为"PASS",表示使用密码进行认证
auth_pass 1111 # 设置密码为"1111",用于进行认证
}
# 设置虚拟IP地址,当keepalived状态切换为MASTER时,此IP会自动添加到系统中
# 当状态切换到BACKUP时,此IP会自动从系统中删除
# 可以通过命令ip addr查看切换后的状态
virtual_ipaddress {
# 虚拟IP地址
172.30.24.96
}
# 集群资源监控,组合vrrp-script进行
track_script {
chk_mysql_port
}
}
检测mysql服务是否在运行脚本 chk_mysql.sh
内容:
#!/bin/bash
counter=$(ps aux | grep -v grep | grep mysqld | wc -l)
if [ "${counter}" -eq "0" ]; then
killall keepalived
fi
2.4 测试启动
# 启动 keepalived
systemctl start keepalived
# 加入开机启动 keepalived
systemctl enable keepalived
# 重新启动 keepalived
systemctl restart keepalived
# 查看 keepalived 状态
systemctl status keepalived
注:示例校验MySQL服务是否运行,需要在MySQL运行的情况下才能正常启动keepalived服务。
启动成功示例:
2.4 卸载
因为中间配置失败,补充一下keepalived的卸载
1、yum安装——卸载 yum remove keepalived
2、源码包安装——卸载
# 安装包的解压目录
cd /home/hd/keepalived-1.2.18
make uninstall
3、第1或2步执行完后,都需要删除相关文件
# 查看相关文件
find / -name keepalived
# 删除找到的文件
rm -rf /etc/keepalived
3、测试
# 此命令可以查看当前实际访问的是哪个数据库
show variables like "%server_id%";
- 在不同数据库上执行:
- 对虚拟出ip 172.30.24.96的数据库进行访问。
查询结果为1,说明当前实际上走的是172.30.24.97上的数据库。
- 手动停止172.30.24.97上的数据库服务。
再次查看172.30.24.96,如果查询成功且server_id成功变成2,说明数据库自动故障转移成功。
4、其他
- keepalived配置,最初使用的是172.30.24.97主节点配置
state MASTER
、172.30.24.98子节点配置state BACKUP
。
测试现象(从两台都未启动状态开始)
1、启动172.30.24.98,vip指向172.30.24.98。
2、启动172.30.24.97,vip指向172.30.24.97。
3、停掉172.30.24.97,vip指向172.30.24.98。
4、启动172.30.24.97,vip指向172.30.24.97。
一开始我以为是配置的MASTER生效了,一直都以172.30.24.97为主。
后来换了下顺序
6、停掉172.30.24.98,vip指向172.30.24.97。
7、启动172.30.24.98,vip指向172.30.24.98。
总结现象是:谁是最新启动的,谁就是当前的主节点。
为了解决这个又去搜了一下配置文件,发现了一些其他情况。
- 两个配置都使用
state BACKUP
如果两个keepalived配置都使用BACKUP,此时虚ip会以优先级高的访问。不论启动先后顺序。
测试现象(从两台都未启动状态开始)
1、启动172.30.24.98,vip指向172.30.24.98。
2、启动172.30.24.97,vip指向172.30.24.97。
3、停掉172.30.24.97,vip指向172.30.24.98。
4、启动172.30.24.97,vip指向172.30.24.97。
6、停掉172.30.24.98,vip指向172.30.24.97。
7、启动172.30.24.98,vip指向172.30.24.97。
可以看到最后一步结果有所不同,总结现象是:只要有优先级高的服务启动,就会vip漂移到优先级高的服务上。
- 172.30.24.97主节点配置
state MASTER
、172.30.24.98子节点配置state BACKUP
;优先级高的172.30.24.97配置添加属性nopreempt # 不抢占模式,在优先级高的机器上设置即可,优先级低的机器可不设置
vrrp_instance VI_1 {
state BACKUP # 设置的当前主机为主节点,如果是备用节点,则设置为BACKUP
interface ens3 # 主机网卡 可以用ifconfig查看来决定设置哪一个
mcast_src_ip 172.30.24.97 # 主机ip
virtual_router_id 35 # 路由器标识,MASTER和BACKUP必须是一致的
priority 101 # 定义优先级,数字越大,优先级越高,在同一个vrrp_instance下,MASTER的优先级必须大于BACKUP的优先级。这样MASTER故障恢复后,就可以将VIP资源再次抢回来
advert_int 1 # 设置VRRP Advertisement(通告)消息的发送间隔为"1"秒
nopreempt # 不抢占模式,在优先级高的机器上设置即可,优先级低的机器可不设置
authentication { # 设置VRRP的认证信息,用于确保只有经过认证的路由器才能参与VRRP组。
auth_type PASS # 指定认证类型为"PASS",表示使用密码进行认证
auth_pass 1111 # 设置密码为"1111",用于进行认证
}
# 设置虚拟IP地址,当keepalived状态切换为MASTER时,此IP会自动添加到系统中
# 当状态切换到BACKUP时,此IP会自动从系统中删除
# 可以通过命令ip addr查看切换后的状态
virtual_ipaddress {
# 虚拟IP地址
172.30.24.96
}
# 集群资源监控,组合vrrp-script进行
track_script {
chk_mysql_port
}
}
测试现象(从两台都未启动状态开始)
1、启动172.30.24.98,vip指向172.30.24.98。
2、启动172.30.24.97,vip指向172.30.24.97。
3、停掉172.30.24.97,服务不可用。
总结现象是:谁是最新启动的,谁就是当前的主节点,但是nopreempt 模式会禁止优先级更高的备用节点接管 VIP,所以172.30.24.97服务挂掉后,会导致整个服务不可用。直到主节点恢复或者手动操作来切换 VIP 到备用节点。