MySQL主主复制+Keepalived高可用集群搭建与故障切换实战

文章目录

    • 环境准备
    • 一、MySQL主主复制配置
      • [1.1 节点1(192.168.10.120)MySQL配置](#1.1 节点1(192.168.10.120)MySQL配置)
      • [1.2 节点2(192.168.10.125)MySQL配置](#1.2 节点2(192.168.10.125)MySQL配置)
      • [1.3 重启MySQL服务](#1.3 重启MySQL服务)
      • [1.4 配置互为主从关系](#1.4 配置互为主从关系)
      • [注意1:在节点一上操作CHANGE MASTER TO时可能出现报错:](#注意1:在节点一上操作CHANGE MASTER TO时可能出现报错:)
      • [注意2:Slave_SQL_Running:为NO查看Last_SQL_Error: 如果是事务冲突导致,可执行STOP SLAVE; SET GLOBAL SQL_SLAVE_SKIP_COUNTER = 1; START SLAVE;来跳过当前错误事务,让 SQL 线程继续运行。](#注意2:Slave_SQL_Running:为NO查看Last_SQL_Error: 如果是事务冲突导致,可执行STOP SLAVE; SET GLOBAL SQL_SLAVE_SKIP_COUNTER = 1; START SLAVE;来跳过当前错误事务,让 SQL 线程继续运行。)
      • [1.5 验证主主复制](#1.5 验证主主复制)
    • 二、Keepalived高可用配置
      • [2.1 安装Keepalived](#2.1 安装Keepalived)
      • [2.2 节点1(192.168.10.120)Keepalived配置](#2.2 节点1(192.168.10.120)Keepalived配置)
      • [2.3 节点2(192.168.10.125)Keepalived配置](#2.3 节点2(192.168.10.125)Keepalived配置)
      • [2.4 创建MySQL检测脚本](#2.4 创建MySQL检测脚本)
      • [2.5 启动Keepalived服务](#2.5 启动Keepalived服务)
    • 三、高可用集群验证与故障切换演示
      • [3.1 初始状态验证](#3.1 初始状态验证)
      • [注意1:如果无法访问数据库,应该先进行赋权。GRANT ALL PRIVILEGES ON *.* TO 'root'@'192.168.10.120' IDENTIFIED BY '123456' WITH GRANT OPTION;](#注意1:如果无法访问数据库,应该先进行赋权。GRANT ALL PRIVILEGES ON . TO 'root'@'192.168.10.120' IDENTIFIED BY '123456' WITH GRANT OPTION;)
      • [3.2 模拟节点1故障](#3.2 模拟节点1故障)
      • [3.3 观察故障切换过程](#3.3 观察故障切换过程)
      • [3.4 恢复节点1](#3.4 恢复节点1)
    • 四、常见问题与解决方法
      • [4.1 执行CHANGE MASTER TO时报错](#4.1 执行CHANGE MASTER TO时报错)
      • [4.2 主从复制状态异常](#4.2 主从复制状态异常)
      • [4.3 VIP无法漂移](#4.3 VIP无法漂移)
    • 五、总结

在企业级应用中,数据库的高可用性至关重要。本文将详细介绍如何基于MySQL主主复制和Keepalived实现数据库高可用架构,通过自动故障切换确保服务连续性。我们将使用两台服务器节点搭建集群,并演示完整的故障切换过程。

环境准备

本次实战使用的环境配置如下:

  • 节点1(master1):192.168.10.120
  • 节点2(master2):192.168.10.125
  • 虚拟IP(VIP):192.168.10.200
  • 操作系统:CentOS 7
  • 软件版本:MySQL 5.7 + Keepalived 1.3.5

一、MySQL主主复制配置

主主复制(互为主从)是指两个MySQL节点互相作为对方的主库和从库,实现双向数据同步,为高可用架构提供数据基础。

1.1 节点1(192.168.10.120)MySQL配置

修改MySQL配置文件/etc/my.cnf(或根据实际路径调整):

ini 复制代码
[client]
port = 3306
socket=/usr/local/mysql/mysql.sock

[mysqld]
user = mysql
basedir=/usr/local/mysql
datadir=/usr/local/mysql/data
port = 3306
character-set-server=utf8
pid-file = /usr/local/mysql/mysqld.pid
socket=/usr/local/mysql/mysql.sock
bind-address = 0.0.0.0
skip-name-resolve
max_connections=2048
default-storage-engine=INNODB
max_allowed_packet=16M
# 主从复制核心配置
server-id = 1  # 节点唯一ID,不可重复
log_bin = /usr/local/mysql/data/mysql-bin.log  # 启用二进制日志
relay_log = /usr/local/mysql/data/mysql-relay-bin.log  # 启用中继日志
relay_log_index = /usr/local/mysql/data/mysql-relay-bin.index
log_slave_updates = 1  # 允许从库更新写入自身binlog(主主复制必需)
auto_increment_offset = 1  # 自增起始值
auto_increment_increment = 2  # 自增步长,避免主键冲突
sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_AUTO_VALUE_ON_ZERO,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,PIPES_AS_CONCAT,ANSI_QUOTES

[mysql]
port = 3306
default-character-set=utf8
socket=/usr/local/mysql/mysql.sock
auto-rehash

1.2 节点2(192.168.10.125)MySQL配置

修改MySQL配置文件/etc/my.cnf

ini 复制代码
[client]
port = 3306
socket=/usr/local/mysql/mysql.sock

[mysqld]
user = mysql
basedir=/usr/local/mysql
datadir=/usr/local/mysql/data
port = 3306
character-set-server=utf8
pid-file = /usr/local/mysql/mysqld.pid
socket=/usr/local/mysql/mysql.sock
bind-address = 0.0.0.0
skip-name-resolve
max_connections=2048
default-storage-engine=INNODB
max_allowed_packet=16M
# 主从复制核心配置
server-id = 2  # 节点唯一ID,与节点1不同
log_bin = /usr/local/mysql/data/master-bin  # 启用二进制日志
relay_log = /usr/local/mysql/data/relay-log-bin  # 启用中继日志
relay_log_index = /usr/local/mysql/data/relay-log-bin.index
log_slave_updates = 1  # 允许从库更新写入自身binlog
auto_increment_offset = 2  # 自增起始值,与节点1不同
auto_increment_increment = 2  # 自增步长,与节点1相同
sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_AUTO_VALUE_ON_ZERO,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,PIPES_AS_CONCAT,ANSI_QUOTES

[mysql]
port = 3306
socket=/usr/local/mysql/mysql.sock
auto-rehash

1.3 重启MySQL服务

在两个节点上分别重启MySQL服务,使配置生效:

bash 复制代码
# 停止MySQL服务
systemctl stop mysqld

# 启动MySQL服务
systemctl start mysqld

# 设置开机自启
systemctl enable mysqld

1.4 配置互为主从关系

步骤1:在节点1创建同步用户

登录节点1的MySQL命令行:

bash 复制代码
mysql -u root -p

执行以下SQL创建用于同步的用户:

sql 复制代码
-- 创建同步用户(允许节点2连接)
CREATE USER 'repl'@'192.168.10.125' IDENTIFIED BY 'YourStrongPassword';
-- 授予复制权限
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'192.168.10.125';
-- 刷新权限
FLUSH PRIVILEGES;

-- 查看节点1的主库状态(记录File和Position值)
SHOW MASTER STATUS;

执行结果类似:

复制代码
+------------------+----------+--------------+------------------+-------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000001 |      154 |              |                  |                   |
+------------------+----------+--------------+------------------+-------------------+
步骤2:在节点2配置作为节点1的从库

登录节点2的MySQL命令行:

bash 复制代码
mysql -u root -p

执行以下SQL配置从库:

sql 复制代码
-- 先停止slave线程(如果已配置)
STOP SLAVE;

-- 配置主库信息(替换为实际的File和Position值)
CHANGE MASTER TO
MASTER_HOST='192.168.10.120',
MASTER_USER='repl',
MASTER_PASSWORD='YourStrongPassword',
MASTER_LOG_FILE='mysql-bin.000001',  -- 节点1的File值
MASTER_LOG_POS=154;  -- 节点1的Position值

-- 启动从库
START SLAVE;

-- 查看从库状态(确保Slave_IO_Running和Slave_SQL_Running均为Yes)
SHOW SLAVE STATUS\G
步骤3:在节点2创建同步用户

继续在节点2的MySQL命令行执行:

sql 复制代码
-- 创建同步用户(允许节点1连接)
CREATE USER 'repl'@'192.168.10.120' IDENTIFIED BY 'YourStrongPassword';
-- 授予复制权限
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'192.168.10.120';
-- 刷新权限
FLUSH PRIVILEGES;

-- 查看节点2的主库状态(记录File和Position值)
SHOW MASTER STATUS;
步骤4:在节点1配置作为节点2的从库

登录节点1的MySQL命令行,执行:

sql 复制代码
-- 先停止slave线程
STOP SLAVE;

-- 配置主库信息(替换为节点2的实际信息)
CHANGE MASTER TO
MASTER_HOST='192.168.10.125',
MASTER_USER='repl',
MASTER_PASSWORD='YourStrongPassword',
MASTER_LOG_FILE='master-bin.000001',  -- 节点2的File值
MASTER_LOG_POS=154;  -- 节点2的Position值

-- 启动从库
START SLAVE;

-- 查看从库状态(确保Slave_IO_Running和Slave_SQL_Running均为Yes)
SHOW SLAVE STATUS\G

注意1:在节点一上操作CHANGE MASTER TO时可能出现报错:

解决方法:在节点一上执行SLAVE IO_THREAD;

后重新执行CHANGE MASTER TO。最后再执行START SLAVE;

SHOW SLAVE STATUS\G查看互为主从的同步状态是否正确:

注意2:Slave_SQL_Running:为NO查看Last_SQL_Error: 如果是事务冲突导致,可执行STOP SLAVE; SET GLOBAL SQL_SLAVE_SKIP_COUNTER = 1; START SLAVE;来跳过当前错误事务,让 SQL 线程继续运行。

1.5 验证主主复制

在节点1创建测试数据库和表:

sql 复制代码
CREATE DATABASE testdb;
USE testdb;
CREATE TABLE users (id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(50));
INSERT INTO users (name) VALUES ('test1');

在节点2查看是否同步成功:

sql 复制代码
USE testdb;
SELECT * FROM users;

同样,在节点2插入数据,检查节点1是否同步:

sql 复制代码
INSERT INTO users (name) VALUES ('test2');

在节点1验证:

sql 复制代码
USE testdb;
SELECT * FROM users;

如果两边都能看到新增的数据,说明主主复制配置成功。

二、Keepalived高可用配置

Keepalived通过VRRP(虚拟路由冗余协议)实现虚拟IP的漂移,当主节点故障时自动将VIP切换到备用节点,实现高可用。

2.1 安装Keepalived

在两个节点上分别安装Keepalived:

bash 复制代码
yum install -y keepalived

2.2 节点1(192.168.10.120)Keepalived配置

创建或修改配置文件/etc/keepalived/keepalived.conf

conf 复制代码
global_defs {
    router_id LVS_MASTER1  # 节点唯一标识
}

# 定义MySQL检测脚本
vrrp_script check_mysql {
    script "/etc/keepalived/check_mysql.sh"  # 检测脚本路径
    interval 2  # 检测间隔(秒)
    weight 2    # 权重调整值
    fall 3      # 连续失败3次视为故障
    rise 2      # 连续成功2次视为恢复
}

vrrp_instance VI_1 {
    state MASTER          # 初始状态为主节点
    interface ens33        # 网络接口(根据实际情况修改)
    virtual_router_id 51  # 虚拟路由ID(两个节点必须相同)
    priority 100          # 优先级(主节点高于备用节点)
    advert_int 1          # 心跳间隔(秒)

    # 认证配置
    authentication {
        auth_type PASS
        auth_pass 1111    # 认证密码(两个节点必须相同)
    }

    # 虚拟IP配置
    virtual_ipaddress {
        192.168.10.200/24  # 虚拟IP地址
    }

    # 引用检测脚本
    track_script {
        check_mysql
    }
}

2.3 节点2(192.168.10.125)Keepalived配置

创建或修改配置文件/etc/keepalived/keepalived.conf

conf 复制代码
global_defs {
    router_id LVS_MASTER2  # 节点唯一标识
}

# 定义MySQL检测脚本
vrrp_script check_mysql {
    script "/etc/keepalived/check_mysql.sh"
    interval 2
    weight 2
    fall 3
    rise 2
}

vrrp_instance VI_1 {
    state BACKUP          # 初始状态为备用节点
    interface ens33        # 网络接口(与节点1一致)
    virtual_router_id 51  # 与节点1相同
    priority 90           # 优先级低于主节点
    advert_int 1

    authentication {
        auth_type PASS
        auth_pass 1111    # 与节点1相同
    }

    virtual_ipaddress {
        192.168.10.200/24  # 相同的虚拟IP
    }

    track_script {
        check_mysql
    }
}

2.4 创建MySQL检测脚本

在两个节点上创建相同的检测脚本/etc/keepalived/check_mysql.sh

bash 复制代码
#!/bin/bash
# 检测MySQL是否正常运行

# 尝试连接MySQL并执行简单命令
mysql -uroot -p123456 -e "show status;" > /dev/null 2>&1

# 检查命令执行结果
if [ $? -ne 0 ]; then
    # MySQL异常,停止Keepalived让VIP漂移
    systemctl stop keepalived
fi

为脚本添加执行权限:

bash 复制代码
chmod +x /etc/keepalived/check_mysql.sh

2.5 启动Keepalived服务

在两个节点上分别启动Keepalived服务:

bash 复制代码
# 启动服务
systemctl start keepalived

# 设置开机自启
systemctl enable keepalived

# 查看服务状态
systemctl status keepalived

三、高可用集群验证与故障切换演示

3.1 初始状态验证

  1. 查看虚拟IP所在节点:

在节点1执行:

bash 复制代码
ip addr show ens33 | grep 192.168.10.200

我的VIP现在在节点1上

正常情况下,VIP(192.168.10.200)应在节点1上。

  1. 通过VIP连接数据库验证:
bash 复制代码
mysql -h 192.168.10.200 -u root -p

应能成功连接到数据库。

注意1:如果无法访问数据库,应该先进行赋权。GRANT ALL PRIVILEGES ON . TO 'root'@'192.168.10.120' IDENTIFIED BY '123456' WITH GRANT OPTION;

FLUSH PRIVILEGES;

3.2 模拟节点1故障

在节点1上停止MySQL服务,模拟数据库故障:

bash 复制代码
systemctl stop mysqld

3.3 观察故障切换过程

  1. 查看VIP漂移情况:

在节点2上执行:

bash 复制代码
ip addr show ens33 | grep 192.168.10.200

VIP漂移成功

约10秒后,应能看到VIP已漂移到节点2。

  1. 查看Keepalived日志:
bash 复制代码
tail -f /var/log/messages | grep Keepalived

可以观察到故障检测和VIP切换的日志信息。

  1. 验证业务连续性:

通过VIP连接数据库,确认仍能正常访问:

bash 复制代码
mysql -h 192.168.10.200 -u root -p

在数据库中插入数据,验证服务正常:

sql 复制代码
USE testdb;
INSERT INTO users (name) VALUES ('failover_test');

3.4 恢复节点1

在节点1上重启服务:

bash 复制代码
# 重启MySQL
systemctl start mysqld

# 重启Keepalived
systemctl start keepalived

观察VIP是否根据优先级设置回切到节点1(默认配置下会回切)。

VIP回切成功

检查数据同步情况,确认节点1恢复后能同步节点2上新增的数据:

sql 复制代码
USE testdb;
SELECT * FROM users;

四、常见问题与解决方法

4.1 执行CHANGE MASTER TO时报错

错误信息ERROR 1872 (HY000): Slave failed to initialize relay log info structure from the repository

解决方法

sql 复制代码
# 在操作的节点上执行
STOP SLAVE;
RESET SLAVE ALL;  # 清除原有配置
# 重新执行CHANGE MASTER TO命令

4.2 主从复制状态异常

检查方法

sql 复制代码
SHOW SLAVE STATUS\G

常见问题处理

  • 若Slave_IO_Running为Connecting:检查网络连接、同步用户权限、防火墙设置
  • 若Slave_SQL_Running为No:可能是数据冲突,可通过SET GLOBAL sql_slave_skip_counter = 1;跳过错误后再启动

4.3 VIP无法漂移

检查方法

  1. 确认Keepalived服务是否正常运行
  2. 检查检测脚本是否有执行权限
  3. 查看日志定位问题:tail -f /var/log/messages

五、总结

通过MySQL主主复制和Keepalived的组合,我们实现了一个高可用的数据库集群:

  1. 主主复制确保了两个节点的数据双向同步,为故障切换提供了数据基础
  2. Keepalived通过VRRP协议实现了虚拟IP的自动漂移,确保服务地址不变
  3. 当主节点故障时,系统能自动切换到备用节点,实现业务无感知续跑

这种架构适合对数据库可用性要求较高的场景,能够有效减少因单点故障导致的业务中断时间,是企业级应用的常用高可用解决方案。

相关推荐
gsfl5 小时前
Redis分布式锁
数据库·redis·分布式
Li zlun6 小时前
MySQL 配置管理与日志系统完全指南:从基础到高级优化
数据库·mysql
勇者无畏4046 小时前
MySQL 中一条 SQL 语句的执行流程
sql·mysql·缓存
wzg20166 小时前
vscode 配置使用pyqt5
开发语言·数据库·qt
老朋友此林7 小时前
MongoDB GEO 项目场景 ms-scope 实战
java·数据库·spring boot·mongodb
极限实验室8 小时前
如何使用 INFINI Gateway 对比 ES 索引数据
数据库
Raymond运维9 小时前
MySQL包安装 -- RHEL系列(离线RPM包安装MySQL)
linux·运维·数据库·mysql
养生技术人10 小时前
Oracle OCP认证考试题目详解082系列第45题
运维·数据库·sql·oracle·开闭原则·ocp
奥尔特星云大使11 小时前
mysql主从配置(保姆级)
数据库·mysql·主从复制