平时做技术实践时,很多问题不是概念不会,而是细节没串起来。拿“Mysql数据库高可用群集最佳实践”来说,它看着像小点,放到项目里常会牵出环境、配置、兼容性和维护成本。下面按实际采用顺序,把思路、关键写法和容易踩坑的地方讲清楚,便于大家直接对照操作。
实际处理时,在企业级生产环境里,MySQL 作为核心关系型数据库,单点故障会直接导致业务中断、数据丢失等严重后果。本文基于 CentOS 系统,从零搭建一套MySQL 主从复制 + HAProxy 负载均衡 + Keepalived 双机热备理解这一步时,的高可用架构,实现数据实时同步、读写请求负载分发、故障自动切换三大核心能力。文章包含完整部署步骤、关键设置解析、故障模拟测试与排坑指南,同时补充了架构原理、性能优化与生产环境最佳实践,帮助运维人员更快掌握企业级数据库高可用方案的落地方法。
本次搭建的架构包含 3 个核心组件,各司其职又协同工作:
在这个场景下,MySQL 主从复制基于 ** 二进制日志(Binlog)** 实现,核心流程如下所示:
理解这一步时,HAProxy 作为四层 TCP 代理, 3306 端口,接收客户端的 MySQL 请求,借助设置的负载均衡算法(本次采用最少连接算法leastconn),将请求分发到后端健康的 MySQL 节点。同时借助健康检查,自动剔除故障节点,避免请求转发到不可用的实例上。
实际处理时,Keepalived 基于 VRRP(虚拟路由冗余协议),在两台服务器之间选举出一台主节点,将虚拟 IP(VIP)绑定到主节点的网卡上。主节点定期发送心跳报文给备节点,若备节点在指定时间内未收到心跳,会自动接管 VIP,实现故障自动切换,整个过程业务侧无感知。
| 节点角色 | IP 地址 | 系统版本 | 部署服务 |
|---|---|---|---|
| MySQL Master1 | 192.168.10.101 | CentOS 7/8 | MySQL 8.0 |
| MySQL Master2 | 192.168.10.102 | CentOS 7/8 | MySQL 8.0 |
| HAProxy1+Keepalived1 | 192.168.10.103 | CentOS 7/8 | HAProxy 2.4、Keepalived 2.0 |
| HAProxy2+Keepalived2 | 192.168.10.104 | CentOS 7/8 | HAProxy 2.4、Keepalived 2.0 |
| 虚拟 IP(VIP) | 192.168.10.100 | - | Keepalived 提供,对外访问入口 |
生产环境建议设置防火墙规则,测试环境可直接关闭:
# 临时关闭SELinux
setenforce 0
# 永久关闭SELinux
sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config
# 关闭防火墙
systemctl stop firewalld
systemctl disable firewalld
yum install -y wget vim net-tools ntpdate
# 同步系统时间
ntpdate time.aliyun.com
echo "*/5 * * * * /usr/sbin/ntpdate time.aliyun.com" >> /var/spool/cron/root
# 下载MySQL YUM源
wget https://dev.mysql.com/get/mysql80-community-release-el7-3.noarch.rpm
yum localinstall -y mysql80-community-release-el7-3.noarch.rpm
yum install -y mysql-community-server
# 启动MySQL并设置开机自启
systemctl start mysqld
systemctl enable mysqld
# 获取初始密码
grep "temporary password" /var/log/mysqld.log
# 登录MySQL修改密码
mysql -uroot -p
ALTER USER 'root'@'localhost' IDENTIFIED BY 'Pwd@123456';
FLUSH PRIVILEGES;
Master1 节点设置:
[mysqld]
basedir=/usr/local/mysql
datadir=/usr/local/mysql/data
socket=/usr/local/mysql/data/mysql.sock
port=3306
bind-address=0.0.0.0
skip-name-resolve
# 主从复制核心配置
log-bin=/usr/local/mysql/data/mysql-bin
binlog_format=MIXED
server-id=1 # 两台节点ID必须不同,Master2设置为2
auto-increment-increment=2
auto-increment-offset=1
# 性能优化(适配2G内存)
innodb_buffer_pool_size=512M
max_connections=100
character-set-server=utf8
default-storage-engine=INNODB
Master2 节点只需修改server-id=2和auto-increment-offset=2,其余设置与 Master1 保持一致。修改完成后重启 MySQL:
systemctl restart mysqld
-- 创建复制用户,允许指定IP连接
CREATE USER 'repl'@'192.168.10.%' IDENTIFIED BY '123456';
-- 授予复制权限
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'192.168.10.%';
-- 刷新权限
FLUSH PRIVILEGES;
在 Master1 上执行,拿到当前 Binlog 文件名和位置:
SHOW MASTER STATUS;
记录File和Position字段的值,后续设置从节点时采用。
CHANGE MASTER TO
MASTER_HOST='192.168.10.101',
MASTER_USER='repl',
MASTER_PASSWORD='123456',
MASTER_LOG_FILE='mysql-bin.000001', -- 替换为Master1的Binlog文件名
MASTER_LOG_POS=156; -- 替换为Master1的Binlog位置
-- 启动从节点复制
START SLAVE;
-- 查看复制状态,确保Slave_IO_Running和Slave_SQL_Running都为Yes
SHOW SLAVE STATUSG
结合项目来看,重复上述步骤,在 Master2 上执行SHOW MASTER STATUS拿到 Binlog 信息,随后在 Master1 上设置:
CHANGE MASTER TO
MASTER_HOST='192.168.10.102',
MASTER_USER='repl',
MASTER_PASSWORD='123456',
MASTER_LOG_FILE='mysql-bin.000001', -- 替换为Master2的Binlog文件名
MASTER_LOG_POS=156; -- 替换为Master2的Binlog位置
START SLAVE;
SHOW SLAVE STATUSG
在 Master1 上新建测试库和表,插入数据:
CREATE DATABASE testdb;
USE testdb;
CREATE TABLE t1(id INT,name VARCHAR(20));
INSERT INTO t1 VALUES(1,'master1');
在 Master2 上查询数据,验证是否同步成功:
SELECT * FROM testdb.t1;
实际处理时,反之在 Master2 插入数据,Master1 也能查询到,说明双向主从设置成功。
在 103 和 104 两台节点上安装 HAProxy:
yum install -y haproxy
systemctl enable haproxy
核心设置如下所示,两台节点设置完全一致:
global
log 127.0.0.1 local2
chroot /var/lib/haproxy
pidfile /var/run/haproxy.pid
maxconn 4000
user haproxy
group haproxy
daemon
defaults
mode tcp
log global
option tcplog
option dontlognull
retries 3
timeout connect 5s
timeout client 1m
timeout server 1m
timeout check 5s
maxconn 3000
# MySQL负载均衡配置
listen mysql
bind 0.0.0.0:3306 # 所有IP的3306端口
mode tcp
balance leastconn # 最少连接算法,分发请求到负载最低的节点
server mysql1 192.168.10.101:3306 check port 3306 maxconn 300
server mysql2 192.168.10.102:3306 check port 3306 maxconn 300
设置说明:
balance leastconn:优先将请求转发给当前连接数最少的 MySQL 节点,避免单节点压力过大。check port 3306:HAProxy 会定期检测后端节点的 3306 端口,若端口不通则标记节点为故障,停止转发请求。# 检查配置文件语法
haproxy -c -f /etc/haproxy/haproxy.cfg
# 启动服务
systemctl start haproxy
# 查看3306端口是否
netstat -tulnp | grep 3306
客户端测试连接,采用测试用户连接 HAProxy 的 IP:
mysql -utest -p123456 -h192.168.10.103 -P3306
能成功登录 MySQL,说明 HAProxy 负载均衡设置成功。
在 103 和 104 两台节点上安装:
yum install -y keepalived
systemctl enable keepalived
global_defs {
router_id r1 # 节点标识,两台节点不同
}
# 检测HAProxy状态的脚本
vrrp_script chk_haproxy {
script "/etc/keepalived/chk.sh"
interval 2 # 每2秒检测一次
}
vrrp_instance VI_1 {
state BACKUP # 两台节点都配置为BACKUP,避免抢占
nopreempt # 关闭抢占模式,故障恢复后不抢回VIP
interface ens33 # 绑定的网卡,根据实际修改
virtual_router_id 51 # 虚拟路由ID,两台节点必须相同
priority 100 # 优先级,103节点优先级设为100,104设为99
advert_int 1
authentication {
auth_type PASS
auth_pass 1111 # 认证密码,两台节点必须相同
}
virtual_ipaddress {
192.168.10.100/24 # 虚拟IP
}
track_script {
chk_haproxy # 关联HAProxy检测脚本
}
notify_backup "/etc/init.d/haproxy restart"
notify_fault "/etc/init.d/haproxy stop"
}
只需修改以下参数:
router_id r2
priority 99
其余配置与103节点保持一致
#!/bin/bash
# 检测HAProxy进程是否存在
if [ $(ps -C haproxy --no-header | wc -l) -eq 0 ]; then
# 若进程不存在,停止Keepalived,触发VIP切换
systemctl stop keepalived
fi
赋予脚本执行权限:
chmod +x /etc/keepalived/chk.sh
# 启动服务
systemctl start keepalived
# 查看虚拟IP是否绑定成功(103节点)
ip a
输出中能看到192.168.10.100/24绑定在ens33网卡上,说明 Keepalived 设置成功。
systemctl stop mysqld。mysql1节点被标记为故障,请求自动转发到 Master2。systemctl stop haproxy。192.168.10.100,依然能正常访问 MySQL,业务侧无感知。systemctl stop keepalived。expire_logs_days=7,自动清理 7 天前的 Binlog 文件,避免磁盘占满。listen stats
bind :8080
mode http
stats enable
stats uri /stats
stats auth admin:admin@123
(链接已移除)即可查看负载均衡状态。maxconn参数,避免连接数过多导致性能下降。notify_fault脚本中添加邮件或短信告警,及时通知运维人员故障发生。echo "local0.* /var/log/keepalived.log" >> /etc/rsyslog.conf
systemctl restart rsyslog
mysqldump或 xtrabackup 定期备份数据,备份文件异地存储。SHOW SLAVE STATUSG中Slave_IO_Running为 No。/var/log/haproxy.log日志报错信息。virtual_router_id是否一致、认证密码是否相同、网卡设置是否正确、chk.sh脚本是否有执行权限。落到代码里,总的来说,mysql高可用集群搭建适合结合实际项目边做边理解。先抓住核心思路,再逐步补上细节和边界处理,最后效果会更稳定,也更容易复用。