摘要
在企业级生产环境中,mysql 作为核心关系型数据库,单点故障会直接导致业务中断、数据丢失等严重后果。本文基于 centos 系统,从零搭建一套mysql 主从复制 + haproxy 负载均衡 + keepalived 双机热备的高可用架构,实现数据实时同步、读写请求负载分发、故障自动切换三大核心能力。文章包含完整部署步骤、关键配置解析、故障模拟测试与排坑指南,同时补充了架构原理、性能优化与生产环境最佳实践,帮助运维人员快速掌握企业级数据库高可用方案的落地方法。
一、架构总览与原理剖析
1.1 架构设计图
本次搭建的架构包含 3 个核心组件,各司其职又协同工作:
- mysql 主从复制:2 台 mysql 节点互为主从,实现数据双向同步,解决单点数据故障问题。
- haproxy:作为 tcp 代理,将客户端请求分发到健康的 mysql 节点,实现负载均衡与故障节点剔除。
- keepalived:通过 vrrp 协议实现双机热备,提供虚拟 ip(vip),客户端只需连接 vip 即可访问数据库,后端故障对业务透明。
1.2 各组件核心原理
1.2.1 mysql 主从复制原理
mysql 主从复制基于 ** 二进制日志(binlog)** 实现,核心流程如下:
- 主节点(master)将所有数据变更记录到 binlog 文件中。
- 从节点(slave)的 io 线程连接主节点,拉取 binlog 并写入本地 relay log 文件。
- 从节点的 sql 线程读取 relay log,回放其中的 sql 语句,实现数据与主节点同步。本次采用双向主从复制,两台节点互为主备,可同时处理读写请求,避免传统主从架构中从节点只读的性能瓶颈。
1.2.2 haproxy 负载均衡原理
haproxy 作为四层 tcp 代理,监听 3306 端口,接收客户端的 mysql 请求,通过配置的负载均衡算法(本次采用最少连接算法leastconn),将请求分发到后端健康的 mysql 节点。同时通过健康检查,自动剔除故障节点,避免请求转发到不可用的实例上。
1.2.3 keepalived 双机热备原理
keepalived 基于 vrrp(虚拟路由冗余协议),在两台服务器之间选举出一台主节点,将虚拟 ip(vip)绑定到主节点的网卡上。主节点定期发送心跳报文给备节点,若备节点在指定时间内未收到心跳,会自动接管 vip,实现故障自动切换,整个过程业务侧无感知。
二、环境准备与前置配置
2.1 服务器规划
| 节点角色 | 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 提供,对外访问入口 |
2.2 基础环境配置(所有节点执行)
2.2.1 关闭 selinux 与防火墙
生产环境建议配置防火墙规则,测试环境可直接关闭:
# 临时关闭selinux setenforce 0 # 永久关闭selinux sed -i 's/selinux=enforcing/selinux=disabled/' /etc/selinux/config # 关闭防火墙 systemctl stop firewalld systemctl disable firewalld
2.2.2 安装依赖包与时间同步
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 双向主从复制部署
3.1 mysql 安装与基础配置
3.1.1 安装 mysql(以 8.0 为例)
# 下载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
3.1.2 初始化 mysql 并修改 root 密码
# 获取初始密码 grep "temporary password" /var/log/mysqld.log # 登录mysql修改密码 mysql -uroot -p alter user 'root'@'localhost' identified by 'pwd@123456'; flush privileges;
3.1.3 配置/etc/my.cnf主从参数
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
3.2 创建主从复制账号(两台节点都执行)
-- 创建复制用户,允许指定ip连接 create user 'repl'@'192.168.10.%' identified by '123456'; -- 授予复制权限 grant replication slave on *.* to 'repl'@'192.168.10.%'; -- 刷新权限 flush privileges;
3.3 配置双向主从同步
3.3.1 查看主节点 binlog 信息
在 master1 上执行,获取当前 binlog 文件名和位置:
show master status;
记录file和position字段的值,后续配置从节点时使用。
3.3.2 配置 master2 作为 master1 的从节点
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 status\g
3.3.3 配置 master1 作为 master2 的从节点
重复上述步骤,在 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 status\g
3.4 主从复制验证
在 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 也能查询到,说明双向主从配置成功。
四、haproxy 负载均衡部署
4.1 haproxy 安装
在 103 和 104 两台节点上安装 haproxy:
yum install -y haproxy systemctl enable haproxy
4.2 配置/etc/haproxy/haproxy.cfg
核心配置如下,两台节点配置完全一致:
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 端口,若端口不通则标记节点为故障,停止转发请求。
4.3 启动 haproxy 并验证
# 检查配置文件语法 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 负载均衡配置成功。
五、keepalived 双机热备部署
5.1 keepalived 安装
在 103 和 104 两台节点上安装:
yum install -y keepalived systemctl enable keepalived
5.2 配置/etc/keepalived/keepalived.conf
5.2.1 keepalived1(103 节点)配置
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"
}
5.2.2 keepalived2(104 节点)配置
只需修改以下参数:
router_id r2 priority 99 其余配置与103节点保持一致
5.3 编写 haproxy 状态检测脚本/etc/keepalived/chk.sh
#!/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
5.4 启动 keepalived 并验证 vip
# 启动服务 systemctl start keepalived # 查看虚拟ip是否绑定成功(103节点) ip a
输出中能看到192.168.10.100/24绑定在ens33网卡上,说明 keepalived 配置成功。
六、高可用架构故障模拟与测试
6.1 测试场景 1:mysql 主节点故障
- 手动停止 master1 的 mysql 服务:
systemctl stop mysqld。 - 查看 haproxy 状态,发现
mysql1节点被标记为故障,请求自动转发到 master2。 - 客户端使用 vip 连接 mysql,依然能正常读写数据,业务无中断。
6.2 测试场景 2:haproxy 主节点故障
- 手动停止 103 节点的 haproxy 服务:
systemctl stop haproxy。 - keepalived 检测脚本触发,103 节点的 keepalived 自动停止,vip 自动漂移到 104 节点。
- 客户端连接 vip
192.168.10.100,依然能正常访问 mysql,业务侧无感知。
6.3 测试场景 3:keepalived 主节点故障
- 手动停止 103 节点的 keepalived 服务:
systemctl stop keepalived。 - 备节点 104 的 keepalived 未收到心跳,自动接管 vip。
- 客户端连接 vip,访问正常,故障切换时间约 1-3 秒。
七、架构优化与生产环境最佳实践
7.1 mysql 主从复制优化
- 半同步复制:在 mysql 5.7 + 中开启半同步复制,确保主节点数据写入后,至少有一个从节点同步成功,避免数据丢失。
- binlog 日志清理:配置
expire_logs_days=7,自动清理 7 天前的 binlog 文件,避免磁盘占满。 - 读写分离:结合中间件(如 mycat、shardingsphere)实现读写分离,读请求分发到从节点,减轻主节点压力。
7.2 haproxy 优化
- 配置监控页面:开启 haproxy 的统计页面,方便实时查看后端节点状态:
浏览器访问
listen stats bind :8080 mode http stats enable stats uri /stats stats auth admin:admin@123http://192.168.10.103:8080/stats即可查看负载均衡状态。 - 调整最大连接数:根据业务并发量调整
maxconn参数,避免连接数过多导致性能下降。
7.3 keepalived 优化
- 故障切换告警:在
notify_fault脚本中添加邮件或短信告警,及时通知运维人员故障发生。 - 日志配置:将 keepalived 日志写入独立文件,方便故障排查:
echo "local0.* /var/log/keepalived.log" >> /etc/rsyslog.conf systemctl restart rsyslog
7.4 安全加固
- mysql 用户权限最小化:仅授予业务用户必要的权限,禁止使用 root 用户连接数据库。
- 防火墙规则配置:仅允许业务服务器 ip 访问 mysql 的 3306 端口,禁止公网直接访问。
- 定期备份:使用
mysqldump或 xtrabackup 定期备份数据,备份文件异地存储。
八、常见问题与排坑指南
8.1 mysql 主从复制故障
- 故障现象:
show slave status\g中slave_io_running为 no。 - 排查思路:检查主从节点网络连通性、复制用户权限、binlog 文件和位置是否正确、防火墙是否放行 3306 端口。
8.2 haproxy 无法转发请求
- 故障现象:客户端连接 haproxy 的 3306 端口超时。
- 排查思路:检查 haproxy 配置文件语法、后端 mysql 节点状态、3306 端口是否被防火墙拦截、
/var/log/haproxy.log日志报错信息。
8.3 keepalived vip 无法漂移
- 故障现象:主节点故障后,vip 未切换到备节点。
- 排查思路:检查两台节点的
virtual_router_id是否一致、认证密码是否相同、网卡配置是否正确、chk.sh脚本是否有执行权限。
总结
到此这篇关于mysql数据库高可用群集最佳实践的文章就介绍到这了,更多相关mysql高可用群集内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论