主主复制·(互为主从)·高可用·keepalived 故障切换演示 并且描述故障切换
一、环境准备(具体配置)
1. 服务器基础信息
节点 | IP 地址(内网) | 角色 | 安装软件 | 虚拟 IP(VIP) |
---|---|---|---|---|
Node1 | 192.168.1.101 | 初始 Master / 备用 Slave | MySQL 5.7、Keepalived | 192.168.1.200 |
Node2 | 192.168.1.102 | 初始 Slave / 备用 Master | MySQL 5.7、Keepalived | 192.168.1.200 |
2. 基础环境初始化(两台节点均执行)
(1)关闭防火墙和 SELinux
bash
# 关闭防火墙
systemctl stop firewalld
systemctl disable firewalld# 临时关闭SELinux
setenforce 0
# 永久关闭SELinux(重启生效)
sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config
(2)配置主机名解析(避免依赖 DNS)
编辑 /etc/hosts
文件,添加以下内容:
bash
vi /etc/hosts
192.168.1.101 node1
192.168.1.102 node2
(3)安装依赖包
bash
yum install -y wget gcc gcc-c++ make openssl-devel
二、搭建 MySQL 主主复制(互为主从)
步骤 1:安装 MySQL 5.7(两台节点均执行)
(1)下载 MySQL YUM 源
bash
wget https://dev.mysql.com/get/mysql57-community-release-el7-11.noarch.rpm
rpm -ivh mysql57-community-release-el7-11.noarch.rpm
(2)安装 MySQL 并启动服务
bash
yum install -y mysql-community-server
systemctl start mysqld
systemctl enable mysqld
(3)获取初始密码并修改
bash
# 查看初始密码(日志中筛选"temporary password")
grep 'temporary password' /var/log/mysqld.log# 登录MySQL并修改密码(需符合复杂度:大小写+数字+特殊符号)
mysql -u root -p
ALTER USER 'root'@'localhost' IDENTIFIED BY 'MySQL@123';
步骤 2:配置 Node1 为主库(允许 Node2 同步)
(1)修改 MySQL 配置文件 /etc/my.cnf
bash
vi /etc/my.cnf
# 添加以下内容(关键参数)
[mysqld]
server-id=101 # 唯一标识,两台节点必须不同(Node1用101,Node2用102)
log-bin=mysql-bin # 开启二进制日志(主从复制依赖)
binlog_format=ROW # 二进制日志格式(推荐ROW,避免数据不一致)
auto-increment-increment=2 # 自增步长(主主复制避免主键冲突)
auto-increment-offset=1 # 自增起始值(Node1从1开始,Node2从2开始)
log-slave-updates=1 # 允许从库将同步的操作写入自身二进制日志(主主必需)
relay-log=relay-log # 开启中继日志(从库必需)
(2)重启 MySQL 并授权同步账号
bash
systemctl restart mysqld# 登录MySQL,授权Node2的同步账号(允许192.168.1.102访问)
mysql -u root -pMySQL@123
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'192.168.1.102' IDENTIFIED BY 'Repl@123';
FLUSH PRIVILEGES;# 查看Node1的二进制日志状态(记录File和Position,后续Node2配置需用)
SHOW MASTER STATUS;
# 示例输出:
# +------------------+----------+--------------+------------------+-------------------+
# | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
# +------------------+----------+--------------+------------------+-------------------+
# | mysql-bin.000001 | 447 | | | |
# +------------------+----------+--------------+------------------+-------------------+
步骤 3:配置 Node2 为主库(允许 Node1 同步)
(1)修改 MySQL 配置文件 /etc/my.cnf
bash
vi /etc/my.cnf
# 添加以下内容(注意server-id和自增参数与Node1不同)
[mysqld]
server-id=102 # 唯一标识,与Node1的101区分
log-bin=mysql-bin
binlog_format=ROW
auto-increment-increment=2 # 步长与Node1一致,避免主键冲突
auto-increment-offset=2 # 起始值为2,与Node1的1错开
log-slave-updates=1
relay-log=relay-log
(2)重启 MySQL 并授权同步账号
bash
systemctl restart mysqld# 登录MySQL,授权Node1的同步账号(允许192.168.1.101访问)
mysql -u root -pMySQL@123
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'192.168.1.101' IDENTIFIED BY 'Repl@123';
FLUSH PRIVILEGES;# 查看Node2的二进制日志状态(记录File和Position,后续Node1配置需用)
SHOW MASTER STATUS;
# 示例输出:
# +------------------+----------+--------------+------------------+-------------------+
# | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
# +------------------+----------+--------------+------------------+-------------------+
# | mysql-bin.000001 | 447 | | | |
# +------------------+----------+--------------+------------------+-------------------+
步骤 4:开启双向同步(完成主主复制)
(1)在 Node2 上配置 “同步 Node1”(Node2 作为 Node1 的从库)
登录 Node2 的 MySQL,执行以下命令(需替换MASTER_LOG_FILE
和MASTER_LOG_POS
为步骤 2 中 Node1 的SHOW MASTER STATUS
结果):
sql
CHANGE MASTER TO
MASTER_HOST='192.168.1.101', # Node1的IP
MASTER_USER='repl', # 同步账号
MASTER_PASSWORD='Repl@123', # 同步密码
MASTER_LOG_FILE='mysql-bin.000001', # Node1的二进制日志文件名
MASTER_LOG_POS=447; # Node1的二进制日志位置# 启动从库同步
START SLAVE;# 查看同步状态(确保Slave_IO_Running和Slave_SQL_Running均为Yes)
SHOW SLAVE STATUS\G;
(2)在 Node1 上配置 “同步 Node2”(Node1 作为 Node2 的从库)
登录 Node1 的 MySQL,执行以下命令(需替换MASTER_LOG_FILE
和MASTER_LOG_POS
为步骤 3 中 Node2 的SHOW MASTER STATUS
结果):
sql
CHANGE MASTER TO
MASTER_HOST='192.168.1.102', # Node2的IP
MASTER_USER='repl',
MASTER_PASSWORD='Repl@123',
MASTER_LOG_FILE='mysql-bin.000001', # Node2的二进制日志文件名
MASTER_LOG_POS=447; # Node2的二进制日志位置# 启动从库同步
START SLAVE;# 查看同步状态(确保Slave_IO_Running和Slave_SQL_Running均为Yes)
SHOW SLAVE STATUS\G;
(3)验证主主复制
- 在 Node1 上创建测试库和表:
sql
CREATE DATABASE test_ha; USE test_ha; CREATE TABLE user (id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(20)); INSERT INTO user (name) VALUES ('node1_test');
- 在 Node2 上查看是否同步:
sql
USE test_ha; SELECT * FROM user; # 应能看到id=1,name=node1_test
- 在 Node2 上插入数据,Node1 上验证同步:
sql
INSERT INTO user (name) VALUES ('node2_test');
- 在 Node1 上查看:
sql
SELECT * FROM user; # 应能看到id=2,name=node2_test(自增步长2,无冲突)
至此,MySQL 主主复制搭建完成,两台节点数据双向同步。
三、配置 Keepalived 实现高可用(VIP 漂移)
步骤 1:安装 Keepalived(两台节点均执行)
bash
yum install -y keepalived
步骤 2:配置 Node1 的 Keepalived(初始 Master 节点)
编辑配置文件 /etc/keepalived/keepalived.conf
,核心是监控 MySQL 状态+设置 VIP:
bash
vi /etc/keepalived/keepalived.conf
# 清空默认内容,添加以下配置
! Configuration File for keepalived
global_defs {router_id LVS_NODE1 # 节点标识,两台节点需不同(Node1用LVS_NODE1,Node2用LVS_NODE2)
}# 配置健康检查脚本(监控MySQL是否存活)
vrrp_script check_mysql {script "/etc/keepalived/check_mysql.sh" # 脚本路径(后续创建)interval 2 # 检查间隔(秒)weight -20 # 若MySQL故障,权重减20(触发切换)
}# 配置VRRP实例(VIP相关)
vrrp_instance VI_1 {state MASTER # 初始状态:MASTER(Node1)/BACKUP(Node2)interface eth0 # 绑定VIP的网卡(需根据实际网卡名修改,用ip addr查看)virtual_router_id 51 # 虚拟路由ID,两台节点必须一致(0-255)priority 100 # 优先级:MASTER节点优先级高于BACKUP(Node1用100,Node2用90)advert_int 1 # VRRP通告间隔(秒)authentication {auth_type PASS # 认证方式auth_pass 1111 # 认证密码,两台节点必须一致}# 绑定虚拟IP(VIP)virtual_ipaddress {192.168.1.200/24 # VIP及子网掩码}# 调用健康检查脚本track_script {check_mysql}
}
步骤 3:配置 Node2 的 Keepalived(初始 Backup 节点)
编辑 /etc/keepalived/keepalived.conf
,仅需修改router_id
、state
和priority
,其他与 Node1 一致:
bash
vi /etc/keepalived/keepalived.conf
! Configuration File for keepalived
global_defs {router_id LVS_NODE2 # 与Node1的LVS_NODE1区分
}vrrp_script check_mysql {script "/etc/keepalived/check_mysql.sh"interval 2weight -20
}vrrp_instance VI_1 {state BACKUP # 初始状态为BACKUPinterface eth0 # 与Node1的网卡一致virtual_router_id 51 # 与Node1一致priority 90 # 优先级低于Node1(100)advert_int 1authentication {auth_type PASSauth_pass 1111 # 与Node1一致}virtual_ipaddress {192.168.1.200/24}track_script {check_mysql}
}
步骤 4:创建 MySQL 健康检查脚本(两台节点均执行)
脚本功能:检查 MySQL 进程是否存活,若不存活则返回非 0 值,触发 Keepalived 权重降低。
bash
# 创建脚本文件
vi /etc/keepalived/check_mysql.sh
# 添加以下内容
#!/bin/bash
# 检查MySQL是否能正常连接(通过mysqladmin命令)
mysqladmin -u root -pMySQL@123 ping > /dev/null 2>&1
if [ $? -ne 0 ]; then# MySQL故障,返回1(触发权重降低)exit 1
else# MySQL正常,返回0exit 0
fi# 给脚本添加执行权限
chmod +x /etc/keepalived/check_mysql.sh
步骤 5:启动 Keepalived 并验证 VIP(两台节点均执行)
bash
# 启动Keepalived
systemctl start keepalived
systemctl enable keepalived# 验证VIP绑定情况(在Node1上执行,应能看到192.168.1.200)
ip addr show eth0
# 示例输出(关键行):
# inet 192.168.1.101/24 brd 192.168.1.255 scope global eth0
# inet 192.168.1.200/24 scope global secondary eth0 # VIP绑定在Node1# 在Node2上执行,应看不到VIP(初始BACKUP状态)
ip addr show eth0 # 仅显示192.168.1.102
四、故障切换演示(核心环节)
场景 1:模拟 Node1(初始 Master)MySQL 故障
步骤 1:停止 Node1 的 MySQL 服务(模拟故障)
bash
# 在Node1上执行,关闭MySQL
systemctl stop mysqld
步骤 2:观察 Keepalived 健康检查与 VIP 漂移
- 在 Node1 上查看 VIP 是否消失:
bash
ip addr show eth0 # 192.168.1.200已消失,仅保留192.168.1.101
- 在 Node2 上查看 VIP 是否绑定:
bash
ip addr show eth0 # 新增192.168.1.200/24,VIP漂移到Node2 # 示例输出: # inet 192.168.1.102/24 brd 192.168.1.255 scope global eth0 # inet 192.168.1.200/24 scope global secondary eth0
- 查看 Keepalived 日志(验证切换原因):
bash
tail -f /var/log/messages | grep Keepalived # 关键日志(Node2): # Keepalived_vrrp[xxxx]: VRRP_Instance(VI_1) Transition to MASTER STATE # Keepalived_vrrp[xxxx]: VRRP_Instance(VI_1) Entering MASTER STATE
步骤 3:验证应用通过 VIP 访问数据库(业务连续性)
在客户端(如另一台服务器或本地虚拟机)通过 VIP 连接 MySQL,验证服务可用:
bash
# 客户端执行(用VIP 192.168.1.200连接)
mysql -h 192.168.1.200 -u root -pMySQL@123# 连接成功后,插入数据(验证写入正常)
USE test_ha;
INSERT INTO user (name) VALUES ('failover_test');
SELECT * FROM user; # 应能看到新数据,说明Node2正常提供服务
场景 2:Node1 故障恢复,重新加入集群
步骤 1:修复 Node1 的 MySQL(重启服务)
bash
# 在Node1上执行,重启MySQL
systemctl start mysqld# 验证Node1的MySQL是否同步Node2故障期间的数据
mysql -u root -pMySQL@123
USE test_ha;
SELECT * FROM user; # 应能看到“failover_test”(Node2故障期间插入的数据),主主同步恢复
步骤 2:观察 VIP 是否自动回切(默认不回切,需手动配置)
Keepalived 默认非抢占模式(BACKUP 节点成为 MASTER 后,即使原 MA