内容大纲
1 架构
1.1 架构图
1.2 大概的搭建过程:
注: 主从复制要采用gtid模式,需要以下条件
① 101和102搭建mysql双主
② 101和102搭建keepalived, 设定虚拟ip 100,
设置角色为backup,关闭抢占,关联mysql端口检测脚本;
优先启动101上的mysql和keepalived,使得vip落在101上
③ 103作为slave,将对应的主设定为100即可,gtid模式不需要指定bin-log文件名和偏移;
1.3 架构缺点:
①每增加1个mysql从,都会增大mysql主的负担,
②101宕机后,vip会通过keepalived漂移至102, 但是期间有几秒钟会中断业务
③101和102是主备关系,同时只能有一台机器参与工作
2 搭建过程
2.1 准备(本文以centos7为例)
下载 mariadb yum源
https://downloads.mariadb.org/mariadb/repositories/#distro=CentOS&distro_release=centos7-amd64–centos7&mirror=tuna&version=10.5
repo配好后,通过yum安装
yum install -y mariadb-server
mysql安全初始化
mysql_secure_installation
进入mysql,创建同步账户,赋予相应权限
drop user 'data_sync'@'10.4.7.%'
create user 'data_sync'@'10.4.7.%' identified by '123456';
grant replication slave on *.* to 'data_sync'@'10.4.7.%';
flush privileges;
show master status;
2.2 mysql双主
mariadb10.0以后默认启用gtid,无需手动开启;但是mysql需要使用命令手动指定
2.2.1 配置文件:
完整配置(仅写101),103配置仅需指明自身server-id
[root@localhost ~]# cat /etc/my.cnf.d/server.cnf
[mysqld]
server-id=101
log_bin=binlog-mariadb # bin-log文件名
binlog_format = row # 行模式复制
auto-increment-offset = 1 # 自增id的起始值,102改成2
auto-increment-increment = 2 # 自增id的步长
log-slave-updates # 开启级联复制,自身成为中继节点
2.2.2 各mysql中指明复制方向
101/102 如下2项为Yes,则表示正常,
103需要等到keepalived启动后才会显示正常
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
# 101上配置
mysql -e "
change master to master_host='10.4.7.102',
MASTER_PORT = 3306,
master_user='data_sync',
master_password='123456',
master_use_gtid=current_pos;
start slave;
show slave status \G"
# 102上配置
mysql -e "
change master to master_host='10.4.7.101',
MASTER_PORT = 3306,
master_user='data_sync',
master_password='123456',
master_use_gtid=current_pos;
start slave;
show slave status \G"
# 103上配置
mysql -e "
change master to master_host='10.4.7.100',
MASTER_PORT = 3306,
master_user='data_sync',
master_password='123456',
master_use_gtid=current_pos;
start slave;
show slave status \G"
2.3 keepalived 相关:
2.3.1 主的配置(10.4.7.101)
其实角色都配置为backup后,优先级就失去了作用
再配置 nopreempt 后,就没有主备的概念了 (本来就只有2台,谁先启动谁就是主)
[root@localhost ~]# cat /etc/keepalived/keepalived.conf
! Configuration File for keepalived
global_defs {
notification_email {
[email protected]
[email protected]
[email protected]
}
notification_email_from [email protected]
smtp_server 127.0.0.1
smtp_connect_timeout 30
router_id 101
vrrp_skip_check_adv_addr
# vrrp_strict # 开启后vrrp将会以组播方式发布报文,此时不用配置unicast地址
# 但是组播方式每次生成虚拟ip时,都会自动添加一条iptables规则,导致虚拟ip不可访问
vrrp_garp_interval 0
vrrp_gna_interval 0
}
vrrp_script chk_mysql_port { #检测mysql服务是否在运行。有很多方式,比如进程,用脚本检测等等
script "/opt/chk_mysql.sh" #这里通过脚本监测
interval 2 #脚本执行间隔,每2s检测一次
weight -20 #脚本结果导致的优先级变更,检测失败(脚本返回非0)则优先级 -20
fall 2 #检测连续2次失败才算确定是真失败。会用weight减少优先级(1-255之间)
rise 1 #检测1次成功就算成功。但不修改优先级
}
vrrp_instance VI_1 {
state BACKUP
interface ens32
virtual_router_id 121
priority 110
advert_int 1
nopreempt # 非抢占模式
authentication {
auth_type PASS
auth_pass 1211
}
virtual_ipaddress {
10.4.7.100/24 dev ens32 label ens32:1
}
unicast_src_ip 10.4.7.101 # 本机IP地址
unicast_peer { # 对端IP地址,若有多个节点可设多个ip
10.4.7.102 # 上述2行配置意味着各节点间会采用单播交换心跳信息
} # 若要采用组播,则取消注释 vrrp_strict ,并删除上述2行;
# 组播方式每次生成虚拟ip时,都会添加一条iptables,导致虚拟ip不可访问
track_script {
chk_mysql_port
}
}
2.3.2 备的配置(10.4.7.102)
其实角色都配置为backup后,优先级就失去了作用
再配置 nopreempt 后,就没有主备的概念了 (本来就只有2台,谁先启动谁就是主)
[root@localhost ~]# cat /etc/keepalived/keepalived.conf
! Configuration File for keepalived
global_defs {
notification_email {
[email protected]
[email protected]
[email protected]
}
notification_email_from [email protected]
smtp_server 127.0.0.1
smtp_connect_timeout 30
router_id 102
vrrp_skip_check_adv_addr
# vrrp_strict # 开启后vrrp将会以组播方式发布报文,此时不用配置unicast地址
# 但是组播方式每次生成虚拟ip时,都会自动添加一条iptables规则,导致虚拟ip不可访问
vrrp_garp_interval 0
vrrp_gna_interval 0
}
vrrp_script chk_mysql_port { #检测mysql服务是否在运行。有很多方式,比如进程,用脚本检测等等
script "/opt/chk_mysql.sh" #这里通过脚本监测
interval 2 #脚本执行间隔,每2s检测一次
weight -10 #脚本结果导致的优先级变更,检测失败(脚本返回非0)则优先级 -5
fall 2 #检测连续2次失败才算确定是真失败。会用weight减少优先级(1-255之间)
rise 1 #检测1次成功就算成功。但不修改优先级
}
vrrp_instance VI_1 {
state BACKUP
interface ens32
virtual_router_id 121
priority 100
advert_int 1
nopreempt # 非抢占模式
authentication {
auth_type PASS
auth_pass 1211
}
virtual_ipaddress {
10.4.7.100
}
unicast_src_ip 10.4.7.102 # 本机IP地址
unicast_peer { # 对端IP地址,若有多个节点可设多个ip
10.4.7.101 # 上述2行配置意味着各节点间会采用单播交换心跳信息
} # 若要采用组播,则取消注释 vrrp_strict ,并删除上述2行;
# 组播方式每次生成虚拟ip时,都会添加一条iptables,导致虚拟ip不可访问
track_script {
chk_mysql_port
}
}
2.3.3 检测mysql端口的脚本(需授予执行权限)
[root@localhost ~]# cat /opt/chk_mysql.sh
#!/bin/bash
counter=$(netstat -na|grep "LISTEN"|grep "3306"|wc -l)
if [ "${counter}" -eq 0 ]; then
systemctl stop keepalived
fi
chmod +x /opt/chk_mysql.sh
3 验证:
首先需要持续 查询/写入 mysql,
在此期间手动kill 101上的 mysql进程, 同时观察是否能切换,以及切换用时
① 持续查询/写入mysql
此处用root用户密码进行操作
# 插入数据命令
for ((i=1;i<=10000;i++));do \
mysql -u data_sync -p123456 -h 10.4.7.100 -e "insert into test.test (dest_number) values ($i)" 2>&1 > /dev/null \
&& echo "date "+%Y-%m-%d %H:%M:%S"
第$i次插入正常" ;
done
# 查询数据命令
for ((i=1;i<=10000000;i++)); do \
mysql -u data_sync -p123456 -h 10.4.7.103 -e "select * from test.test" 2>&1 >/dev/null \
&& echo "date "+%Y-%m-%d %H:%M:%S"
第$i次查询正常" ;
done
② 手动kill 101的mysql
发现虚拟ip成功切换至102上,证明可以实现热备
期间使用tcpdump抓包, 并通过wireshark打开查看, 发现
正常情况下是101主动通告vrrp心跳信息给102;
当101上的mysql服务被手动kill后,101keepalivrd触发脚本,随即"自杀";
102上的keepalivrd开始接管, 主动通告vrrp心跳信息给101, 说明keepalivrd已完成切换
③ 查看切换间隔时间
业务等待大概3秒左右