MySQL主从复制+Redis集群 数据库高可用实战教程(2024最新版)

在互联网业务中,数据库是核心基础设施,单点数据库一旦故障会直接导致服务中断、数据丢失,造成巨大损失。数据库高可用的核心目标是消除单点故障、保障数据不丢失、服务持续可用。本文聚焦两大主流数据库------关系型数据库MySQL(主从复制架构)和非关系型数据库Redis(集群架构),详解从环境搭建、配置部署到故障切换的完整流程,全程实战导向,新手也能按步骤落地。

一、数据库高可用核心认知

1.1 为什么需要高可用?

单点数据库存在三大致命问题:

  • 硬件故障(硬盘损坏、服务器宕机)导致服务直接中断;
  • 数据库压力突增(高并发查询/写入)时,单点性能瓶颈无法突破;
  • 数据备份不及时或恢复困难,可能造成永久性数据丢失。

高可用架构通过"多节点冗余"解决上述问题,核心实现思路:

  • 数据多副本存储(避免单点数据丢失);
  • 服务多节点部署(故障时自动/手动切换);
  • 读写分离(分摊单点压力,提升并发能力)。

1.2 本文覆盖架构

  • MySQL高可用:一主多从复制架构(1主2从),支持读写分离、故障手动切换(生产环境可搭配MGR或Keepalived实现自动切换);
  • Redis高可用:3主3从Cluster集群架构,支持数据分片存储、自动故障转移、负载均衡。

1.3 前置准备

  • 服务器配置:至少4台CentOS 7.x服务器(MySQL主1台+从2台,Redis集群3台,可复用服务器但推荐独立部署);
  • 基础环境:所有服务器关闭SELinux、配置防火墙规则、同步系统时间;
  • 软件版本:MySQL 8.0(稳定版)、Redis 6.2(支持Cluster集群)。

二、MySQL高可用:主从复制架构部署

MySQL主从复制是关系型数据库高可用的基础方案,通过binlog(二进制日志)实现主库数据向从库同步,支持读写分离(主库写、从库读),大幅提升并发处理能力。

2.1 主从复制原理

  1. 主库开启binlog日志,记录所有数据修改操作(增删改);
  2. 从库通过IO线程连接主库,获取主库的binlog日志并写入本地relay log(中继日志);
  3. 从库通过SQL线程读取relay log,解析日志并执行相同操作,实现与主库数据一致。

2.2 环境规划

角色 服务器IP 核心配置 用途
MySQL主库 192.168.1.30 4核8G,500G硬盘 处理写入请求、同步数据
MySQL从库1 192.168.1.31 4核8G,500G硬盘 处理查询请求、备份
MySQL从库2 192.168.1.32 4核8G,500G硬盘 冗余备份、故障切换

2.3 主库(192.168.1.30)配置步骤

2.3.1 安装MySQL 8.0

bash 复制代码
# 安装MySQL YUM源
wget https://dev.mysql.com/get/mysql80-community-release-el7-7.noarch.rpm
rpm -ivh mysql80-community-release-el7-7.noarch.rpm

# 安装MySQL服务器
yum install -y mysql-community-server --nogpgcheck

# 启动MySQL并设置开机自启
systemctl start mysqld
systemctl enable mysqld

# 获取初始密码
grep 'temporary password' /var/log/mysqld.log | awk '{print $NF}'

2.3.2 初始化MySQL(修改密码、授权)

bash 复制代码
# 登录MySQL
mysql -u root -p

# 修改root密码(MySQL 8.0要求大小写+数字+特殊字符)
ALTER USER 'root'@'localhost' IDENTIFIED BY 'MySQL@123456';

# 创建主从复制专用用户(仅允许从库IP访问)
CREATE USER 'repl'@'192.168.1.%' IDENTIFIED BY 'Repl@123456';
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'192.168.1.%';
FLUSH PRIVILEGES;

# 退出MySQL
exit

2.3.3 配置主库binlog与服务器ID

编辑MySQL配置文件/etc/my.cnf,添加以下配置:

ini 复制代码
[mysqld]
# 服务器唯一ID(主库建议设为1,从库需不同)
server-id = 1
# 开启binlog日志,指定日志存储路径
log-bin = /var/lib/mysql/mysql-bin
# binlog日志格式(row格式支持所有场景,推荐)
binlog_format = row
# 同步的数据库(仅同步指定数据库,可选)
binlog-do-db = web_app
# 忽略同步的数据库(可选)
binlog-ignore-db = mysql
# 避免从库复制时主键冲突
log-slave-updates = 1
# 二进制日志过期时间(7天,避免日志过大)
expire_logs_days = 7

2.3.4 重启MySQL并查看主库状态

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

# 登录MySQL,查看主库状态(记录binlog文件名和位置,后续从库配置用)
mysql -u root -pMySQL@123456
SHOW MASTER STATUS;

执行结果需记录File(如mysql-bin.000001)和Position(如156),后续从库配置需用到。

2.4 从库(192.168.1.31/32)配置步骤

两台从库配置完全一致,以下以192.168.1.31为例。

2.4.1 安装MySQL 8.0

同主库安装步骤,无需重复初始化密码(后续会同步主库数据)。

2.4.2 配置从库服务器ID与中继日志

编辑/etc/my.cnf,添加以下配置:

ini 复制代码
[mysqld]
# 服务器唯一ID(从库1设为2,从库2设为3,必须与主库不同)
server-id = 2
# 开启中继日志
relay-log = /var/lib/mysql/relay-bin
# 中继日志索引文件
relay-log-index = /var/lib/mysql/relay-bin.index
# 从库只读(避免从库写入数据,导致主从不一致)
read_only = 1
# 允许超级用户临时写入(用于维护)
super_read_only = 1
# 同步的数据库
replicate-do-db = web_app
# 忽略同步的数据库
replicate-ignore-db = mysql

2.4.3 重启MySQL并配置主从同步

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

# 登录从库MySQL
mysql -u root -p

# 重置从库同步状态(首次配置必执行)
STOP SLAVE;
RESET SLAVE;

# 配置主从连接(替换为实际主库信息、binlog文件名和位置)
CHANGE MASTER TO
MASTER_HOST='192.168.1.30',
MASTER_USER='repl',
MASTER_PASSWORD='Repl@123456',
MASTER_LOG_FILE='mysql-bin.000001',  # 主库SHOW MASTER STATUS输出的File
MASTER_LOG_POS=156;  # 主库SHOW MASTER STATUS输出的Position

# 启动从库同步线程
START SLAVE;

# 查看从库同步状态
SHOW SLAVE STATUS\G;

2.4.4 验证主从同步状态

执行SHOW SLAVE STATUS\G;后,重点查看两个参数:

  • Slave_IO_Running:YES(IO线程正常);
  • Slave_SQL_Running:YES(SQL线程正常)。 两个参数均为YES,说明主从同步配置成功。

2.5 主从复制实战验证

2.5.1 数据同步验证

  1. 在主库创建web_app数据库并插入测试数据:
mysql 复制代码
CREATE DATABASE IF NOT EXISTS web_app;
USE web_app;
CREATE TABLE user (id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(50));
INSERT INTO user (name) VALUES ('测试用户1'), ('测试用户2');
  1. 在从库查询数据,验证是否同步成功:
mysql 复制代码
USE web_app;
SELECT * FROM user;

若能查询到主库插入的数据,说明数据同步正常。

2.5.2 读写分离配置(可选)

通过应用层实现读写分离(主库写、从库读),以PHP为例:

php 复制代码
// 主库(写操作)
$master_db = new mysqli('192.168.1.30', 'root', 'MySQL@123456', 'web_app');
// 从库(读操作)
$slave_db = new mysqli('192.168.1.31', 'root', 'MySQL@123456', 'web_app');

// 写操作(插入/更新/删除)用主库
$master_db->query("INSERT INTO user (name) VALUES ('读写分离测试')");
// 读操作(查询)用从库
$result = $slave_db->query("SELECT * FROM user");

2.6 主从复制常见问题与解决

2.6.1 Slave_IO_Running=No

  • 原因:主从网络不通、复制用户密码错误、binlog文件名/位置错误;
  • 解决:检查防火墙(开放3306端口)、验证复制用户权限、重新获取主库binlog状态。

2.6.2 Slave_SQL_Running=No

  • 原因:从库数据与主库不一致、表结构冲突、主键重复;
  • 解决:重新同步主库数据(用mysqldump备份主库,从库恢复),执行STOP SLAVE; RESET SLAVE;后重新配置同步。

2.6.3 主从同步延迟

  • 原因:从库性能不足、主库写入量过大、大事务导致;
  • 解决:升级从库硬件、拆分大事务、开启从库并行复制(MySQL 8.0默认支持)。

2.7 故障切换实战(主库宕机)

当主库(192.168.1.30)宕机时,手动切换到从库(192.168.1.31):

  1. 确认主库宕机,登录从库停止同步:
mysql 复制代码
STOP SLAVE;
  1. 解除从库只读限制:
mysql 复制代码
SET GLOBAL read_only = 0;
SET GLOBAL super_read_only = 0;
  1. 应用层修改数据库连接地址,指向新主库(192.168.1.31);

  2. 原主库恢复后,可作为新从库,配置同步新主库数据。

三、Redis高可用:3主3从Cluster集群部署

Redis作为内存数据库,高并发场景下单点故障会导致缓存失效,进而引发数据库雪崩。Redis Cluster集群通过"分片存储+主从复制"实现高可用,支持自动故障转移,无需依赖第三方工具。

3.1 Redis Cluster核心原理

  • 分片存储:将数据按哈希槽(共16384个)分配到不同主节点,每个主节点负责部分哈希槽;
  • 主从复制:每个主节点对应至少1个从节点,主节点故障时,从节点自动升级为主节点;
  • 自动故障转移:通过集群内节点心跳检测,发现主节点故障后,自动触发从节点选举和切换。

3.2 环境规划

服务器IP 节点端口 角色 用途
192.168.1.40 7000、7003 主节点7000、从节点7003 哈希槽分配、数据备份
192.168.1.41 7001、7004 主节点7001、从节点7004 哈希槽分配、数据备份
192.168.1.42 7002、7005 主节点7002、从节点7005 哈希槽分配、数据备份

注:每台服务器部署2个Redis节点(1主1从),生产环境建议主从节点分布在不同服务器,避免单点故障。

3.3 集群部署步骤(所有节点通用)

3.3.1 安装Redis 6.2

bash 复制代码
# 安装依赖
yum install -y gcc gcc-c++ make wget

# 下载Redis源码
wget https://download.redis.io/releases/redis-6.2.14.tar.gz
tar -zxvf redis-6.2.14.tar.gz
cd redis-6.2.14

# 编译安装
make MALLOC=libc
make install PREFIX=/usr/local/redis

# 创建Redis命令软链接
ln -s /usr/local/redis/bin/* /usr/bin/

3.3.2 创建节点目录与配置文件

以192.168.1.40为例,创建7000和7003节点目录:

bash 复制代码
# 创建节点目录
mkdir -p /data/redis/{7000,7003}

# 编写7000节点配置文件(主节点)
cat > /data/redis/7000/redis.conf << EOF
port 7000
daemonize yes
pidfile /var/run/redis-7000.pid
logfile /data/redis/7000/redis.log
dir /data/redis/7000
bind 0.0.0.0
protected-mode no
requirepass Redis@123456
masterauth Redis@123456
cluster-enabled yes
cluster-config-file nodes-7000.conf
cluster-node-timeout 5000
cluster-announce-ip 192.168.1.40
cluster-announce-port 7000
cluster-announce-bus-port 17000
maxmemory 4gb
maxmemory-policy allkeys-lru
EOF

# 编写7003节点配置文件(从节点,仅修改端口相关)
cat > /data/redis/7003/redis.conf << EOF
port 7003
daemonize yes
pidfile /var/run/redis-7003.pid
logfile /data/redis/7003/redis.log
dir /data/redis/7003
bind 0.0.0.0
protected-mode no
requirepass Redis@123456
masterauth Redis@123456
cluster-enabled yes
cluster-config-file nodes-7003.conf
cluster-node-timeout 5000
cluster-announce-ip 192.168.1.40
cluster-announce-port 7003
cluster-announce-bus-port 17003
maxmemory 4gb
maxmemory-policy allkeys-lru
EOF

其他两台服务器(192.168.1.41/42)按相同方式创建节点(端口7001/7004、7002/7005),仅修改cluster-announce-ip为对应服务器IP。

3.3.3 启动所有Redis节点

bash 复制代码
# 192.168.1.40启动节点
redis-server /data/redis/7000/redis.conf
redis-server /data/redis/7003/redis.conf

# 192.168.1.41启动节点
redis-server /data/redis/7001/redis.conf
redis-server /data/redis/7004/redis.conf

# 192.168.1.42启动节点
redis-server /data/redis/7002/redis.conf
redis-server /data/redis/7005/redis.conf

# 验证节点启动状态
ps aux | grep redis-server

3.3.4 创建Redis Cluster集群

在任意一台服务器执行(推荐192.168.1.40):

bash 复制代码
redis-cli -a Redis@123456 --cluster create \
192.168.1.40:7000 192.168.1.41:7001 192.168.1.42:7002 \
192.168.1.40:7003 192.168.1.41:7004 192.168.1.42:7005 \
--cluster-replicas 1
  • --cluster-replicas 1:指定每个主节点对应1个从节点;
  • 执行后会自动分配哈希槽,输入yes确认即可。

3.4 集群验证与测试

3.4.1 查看集群状态

bash 复制代码
# 登录任意节点
redis-cli -h 192.168.1.40 -p 7000 -a Redis@123456

# 查看集群信息
cluster info

# 查看节点列表(包含主从关系、哈希槽分配)
cluster nodes

输出中包含cluster_state:ok,说明集群状态正常。

3.4.2 数据读写测试

bash 复制代码
# 插入数据(自动分配到对应主节点)
set product:1001 '{"name":"测试商品","price":199.9}'

# 查询数据(自动路由到数据所在节点)
get product:1001

# 查看数据所在节点
cluster keyslot product:1001

3.4.3 故障转移测试

手动停止主节点7000,验证从节点7003是否自动升级为主节点:

bash 复制代码
# 停止主节点7000
redis-cli -h 192.168.1.40 -p 7000 -a Redis@123456 shutdown

# 5秒后查看节点状态
redis-cli -h 192.168.1.40 -p 7003 -a Redis@123456 cluster nodes

此时7003会显示为master,原主节点7000故障后,集群自动完成故障转移,服务不中断。

3.5 Redis集群优化与运维

3.5.1 持久化配置(避免数据丢失)

Redis集群默认开启RDB持久化,生产环境建议开启AOF持久化(日志追加模式),修改每个节点的redis.conf

ini 复制代码
appendonly yes
appendfsync everysec  # 每秒同步日志到磁盘

修改后重启所有节点。

3.5.2 内存优化

  • 合理设置maxmemory(根据服务器内存,建议预留20%系统内存);
  • 选择合适的内存淘汰策略(allkeys-lru:优先淘汰最近最少使用的key);
  • 定期清理过期key,避免无效数据占用内存。

3.5.3 集群监控

结合Prometheus+Grafana监控集群状态,核心监控指标:

  • 集群状态(cluster_state);
  • 每个节点的内存使用率、连接数;
  • 哈希槽分配情况;
  • 主从复制状态。

四、数据库高可用生产环境最佳实践

4.1 通用最佳实践

  1. 数据备份策略

    • MySQL:开启binlog,每天全量备份(mysqldump)+ 实时binlog备份;
    • Redis:开启RDB+AOF混合持久化,定期备份RDB文件。
  2. 监控告警

    • 监控数据库服务状态(是否存活)、连接数、查询延迟;
    • 监控数据同步状态(MySQL主从、Redis主从);
    • 设置告警阈值(如MySQL连接数超过80%、Redis内存使用率超过90%),通过邮件/短信告警。
  3. 权限最小化

    • MySQL复制用户仅授予REPLICATION SLAVE权限;
    • Redis集群设置密码,禁止外部直接访问。

4.2 MySQL主从复制优化

  • 生产环境推荐"1主3从"架构,1个从库用于读写分离,1个用于备份,1个用于故障切换;
  • 大表拆分,避免大事务导致同步延迟;
  • 搭配MGR(MySQL Group Replication)实现自动故障切换,无需手动干预。

4.3 Redis集群优化

  • 主从节点分布在不同服务器/机房,避免单点故障;
  • 合理规划哈希槽,避免单个主节点负载过高;
  • 禁止使用KEYSFLUSHDB等危险命令,避免影响集群性能。
相关推荐
你想考研啊11 分钟前
win11安装mysql
数据库·mysql
Gary董14 分钟前
mysql全面优化从哪几方面入手
数据库·mysql
Humbunklung18 分钟前
记一次MySQL数据库备份与SQL格式内容导出导入
数据库·sql·mysql
予枫的编程笔记24 分钟前
【MySQL筑基篇】Schema设计避坑指南:INT/BIGINT、CHAR/VARCHAR选型不再纠结
mysql·数据库设计·三范式·反范式·schema设计·数据类型选型·数据库性能优化
我真的是大笨蛋38 分钟前
MySQL临时表深度解析
java·数据库·sql·mysql·缓存·性能优化
南屿欣风1 小时前
MySQL Binlog 数据恢复实战
数据库·mysql
Wzx1980121 小时前
go聊天室接入mysql的项目docker部署流程
mysql·docker·golang
梦想的旅途21 小时前
企微全自动化运营的可视化与度量
数据库·mysql
定偶1 小时前
C语言操作MYSQL
c语言·mysql·adb
Nandeska2 小时前
11、MySQL主从复制的基本概念
数据库·mysql