摘要:本文从零到一搭建企业级 MySQL 高可用集群,基于MySQL 主主复制 + HAProxy 负载均衡 + Keepalived 虚拟 IP 漂移架构,实现故障自动转移、负载均衡、读写分离,彻底解决 MySQL 单点故障问题,适用于电商、金融等核心业务生产环境。

前言

在数字化时代,数据是企业的核心资产,数据库的可靠性直接决定业务连续性。传统单节点 MySQL 架构存在严重单点故障风险,一旦服务器宕机、硬件损坏或网络中断,将直接导致业务中断、数据丢失,造成巨大经济损失。

为解决这一问题,本文采用开源组件搭建MySQL 高可用集群,通过主主复制实现数据冗余,HAProxy 实现流量负载均衡,Keepalived 实现故障自动切换,最终达成零停机、零数据丢失的业务目标。

一、架构核心原理

1.1 组件协同机制

本架构由三大核心组件组成,各司其职、协同工作,构成完整高可用体系:

表格

组件 核心功能 实现价值
MySQL 主主复制 双节点双向数据同步,均支持读写 消除单点故障,提升写入性能,保证数据一致性
HAProxy 四层 TCP 负载均衡,健康检查,故障节点自动剔除 智能分发流量,避免节点过载,保证服务可用性
Keepalived 基于 VRRP 协议管理虚拟 IP(VIP),故障自动漂移 提供统一访问入口,实现无缝故障切换

1.2 架构优势

  1. 高可用性:全链路冗余设计,任意节点故障不影响业务
  2. 高性能:双主并发写入,读请求负载均衡,提升集群吞吐
  3. 自动化:故障检测、切换、恢复全自动化,无需人工干预
  4. 低成本:全部采用开源组件,无商业授权费用,运维成本低
  5. 易扩展:支持横向扩展 MySQL 节点与代理节点,适配业务增长

二、实验环境规划

2.1 服务器配置

本次实验基于openEuler 24.03系统,MySQL 版本为 8.0.36,服务器规划如下:

表格

主机角色 操作系统 IP 地址 部署服务
MySQL Master1 openEuler 24.03 192.168.10.101 MySQL 8.0.36
MySQL Master2 openEuler 24.03 192.168.10.102 MySQL 8.0.36
HAProxy+Keepalived1 openEuler 24.03 192.168.10.103 HAProxy、Keepalived
HAProxy+Keepalived2 openEuler 24.03 192.168.10.104 HAProxy、Keepalived
虚拟 IP(VIP) - 192.168.10.100 业务统一访问入口

2.2 实验目标

  1. 完成 MySQL 双主架构配置,实现数据双向实时同步
  2. 配置 HAProxy,实现 MySQL 负载均衡与健康检查
  3. 配置 Keepalived,实现 VIP 自动漂移与故障转移
  4. 模拟节点故障,验证集群高可用能力

三、MySQL 双主复制部署

MySQL 主主复制即两台服务器互为主从,双向同步数据,均支持读写操作,是实现高可用的基础。

3.1 基础环境准备

所有节点执行以下操作,关闭防火墙与 SELinux,安装基础依赖:

bash

运行

# 关闭防火墙
systemctl stop firewalld
systemctl disable firewalld

# 关闭SELinux
sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config
setenforce 0

# 安装基础依赖包
dnf install -y gcc vim wget net-tools lrzsz libaio numactl openssl ncurses-compat-libs

3.2 MySQL 二进制安装

  1. 创建 MySQL 专用用户

bash

运行

useradd -M -s /sbin/nologin mysql
  1. 解压并配置 MySQL 安装包

bash

运行

# 解压安装包
tar xJf mysql-8.0.36-linux-glibc2.28-x86_64.tar.xz
# 移动至安装目录
mv mysql-8.0.36-linux-glibc2.28-x86_64 /usr/local/mysql
# 创建数据目录
mkdir -p /usr/local/mysql/data
# 授权目录权限
chown -R mysql.mysql /usr/local/mysql/data
  1. 初始化 MySQL

bash

运行

cd /usr/local/mysql/bin
./mysqld --initialize --user=mysql --basedir=/usr/local/mysql --datadir=/usr/local/mysql/data

关键:记录初始化生成的临时密码,用于首次登录。

  1. 配置 MySQL 配置文件/etc/my.cnf

ini

[mysqld]
socket=/usr/local/mysql/data/mysql.sock
basedir=/usr/local/mysql
datadir=/usr/local/mysql/data
port=3306
bind-address=0.0.0.0  # 允许远程连接
skip-name-resolve     # 禁用DNS解析,提升性能
max_connections=2048  # 最大连接数
character-set-server=utf8  # 字符集
default-storage-engine=INNODB  # 默认存储引擎
max_allowed_packet=16M  # 最大数据包

[client]
socket=/usr/local/mysql/data/mysql.sock
  1. 配置系统服务

bash

运行

# 复制启动脚本
cp /usr/local/mysql/support-files/mysql.server /etc/rc.d/init.d/mysqld
chmod +x /etc/rc.d/init.d/mysqld

# 创建systemd服务文件
cat > /lib/systemd/system/mysqld.service << EOF
[Unit]
Description=mysqld
After=network.target

[Service]
Type=forking
ExecStart=/etc/rc.d/init.d/mysqld start
ExecReload=/etc/rc.d/init.d/mysqld restart
ExecStop=/etc/rc.d/init.d/mysqld stop
PrivateTmp=true

[Install]
WantedBy=multi-user.target
EOF

# 重载服务并启动
systemctl daemon-reload
systemctl enable mysqld
systemctl start mysqld
  1. 修改 root 密码

bash

运行

mysqladmin -u root -p 临时密码 password 'Root@123456'

3.3 双主复制核心配置

3.3.1 配置server-id与二进制日志
  • Master1(192.168.10.101) 修改/etc/my.cnf,添加:

ini

server-id=1  # 唯一ID,不能重复
log-bin=/usr/local/mysql/data/mysql-bin  # 开启二进制日志
binlog_format=MIXED  # 日志格式
  • Master2(192.168.10.102) 修改/etc/my.cnf,添加:

ini

server-id=2  # 唯一ID,不能重复
log-bin=/usr/local/mysql/data/mysql-bin  # 开启二进制日志
binlog_format=MIXED  # 日志格式

重启 MySQL 服务

bash

运行

systemctl restart mysqld
3.3.2 创建复制授权用户

两台 MySQL 均执行,创建用于主从同步的用户:

sql

CREATE USER 'myslave'@'%' IDENTIFIED BY '123456';
GRANT REPLICATION SLAVE ON *.* TO 'myslave'@'%';
# 兼容MySQL8.0认证插件
ALTER USER 'myslave'@'%' IDENTIFIED WITH mysql_native_password BY '123456';
FLUSH PRIVILEGES;
3.3.3 配置主从关联
  1. Master1 指向 Master2

sql

CHANGE MASTER TO
MASTER_HOST='192.168.10.102',
MASTER_USER='myslave',
MASTER_PASSWORD='123456',
MASTER_LOG_FILE='mysql-bin.000001',
MASTER_LOG_POS=157;

# 启动同步
START SLAVE;
  1. Master2 指向 Master1

sql

CHANGE MASTER TO
MASTER_HOST='192.168.10.101',
MASTER_USER='myslave',
MASTER_PASSWORD='123456',
MASTER_LOG_FILE='mysql-bin.000001',
MASTER_LOG_POS=157;

# 启动同步
START SLAVE;
3.3.4 验证同步状态

bash

运行

mysql -uroot -p -e "SHOW SLAVE STATUS\\G" | grep Yes

出现以下结果表示同步成功

plaintext

Slave_IO_Running: Yes
Slave_SQL_Running: Yes

3.4 创建业务测试用户

两台 MySQL 均执行,创建用于业务连接的用户:

sql

CREATE USER 'test'@'192.168.10.%' IDENTIFIED BY '123456';
GRANT ALL ON *.* TO 'test'@'192.168.10.%';
ALTER USER 'test'@'192.168.10.%' IDENTIFIED WITH mysql_native_password BY '123456';
FLUSH PRIVILEGES;

四、HAProxy 负载均衡配置

HAProxy 作为四层 TCP 代理,负责将业务流量分发至两台 MySQL,同时自动检测节点状态,剔除故障节点。

4.1 安装 HAProxy

两台代理节点(103/104)均执行

bash

运行

dnf install -y haproxy

4.2 核心配置文件/etc/haproxy/haproxy.cfg

ini

global
    log 127.0.0.1 local2
    chroot /var/lib/haproxy
    pidfile /var/run/haproxy.pid
    user haproxy
    group haproxy
    daemon
    maxconn 4000  # 最大连接数

defaults
    mode tcp  # 四层TCP模式,适配MySQL
    log global
    option tcplog
    option dontlognull
    retries 3  # 重试次数
    # 超时配置
    timeout http-request 5s
    timeout queue 1m
    timeout connect 5s
    timeout client 1m
    timeout server 1m
    timeout check 5s
    maxconn 3000

# MySQL负载均衡配置
listen mysql
    bind 0.0.0.0:3306  # 监听3306端口
    balance leastconn  # 最少连接数算法
    # 后端MySQL节点
    server mysql1 192.168.10.101:3306 check port 3306 maxconn 300
    server mysql2 192.168.10.102:3306 check port 3306 maxconn 300

4.3 配置说明

表格

配置项 作用
mode tcp 四层代理,支持 MySQL 长连接
balance leastconn 将流量分发给连接数最少的节点,避免过载
check port 3306 健康检查,检测 MySQL 端口是否存活
maxconn 300 限制单节点最大连接数,保护数据库

4.4 启动 HAProxy

bash

运行

# 检查配置语法(关键)
haproxy -c -f /etc/haproxy/haproxy.cfg
# 启动并开机自启
systemctl restart haproxy
systemctl enable haproxy

五、Keepalived 高可用配置

Keepalived 通过VRRP 协议管理虚拟 IP(VIP),当主代理节点故障时,VIP 自动漂移至备用节点,保证业务访问入口不变。

5.1 安装 Keepalived

两台代理节点均执行

bash

运行

dnf install -y keepalived

5.2 配置 HAProxy 监控脚本

创建脚本,当 HAProxy 故障时自动停止 Keepalived,触发 VIP 漂移:

bash

运行

cat > /etc/keepalived/chk.sh << EOF
#!/bin/bash
if [ \$(ps -C haproxy --no-header | wc -l) -eq 0 ]; then
    systemctl stop keepalived
fi
EOF

# 赋予执行权限
chmod +x /etc/keepalived/chk.sh

5.3 Keepalived 配置

5.3.1 Node1(192.168.10.103)配置/etc/keepalived/keepalived.conf

ini

global_defs {
    router_id r1  # 唯一路由ID
}

# 监控HAProxy状态
vrrp_script chk_haproxy {
    script "/etc/keepalived/chk.sh"
    interval 2  # 每2秒检查一次
}

vrrp_instance VI_1 {
    state BACKUP  # 非抢占模式
    nopreempt  # 禁止自动抢占
    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.100
    }
    track_script {
        chk_haproxy
    }
    notify_backup "/etc/init.d/haproxy restart"
    notify_fault "/etc/init.d/haproxy stop"
}
5.3.2 Node2(192.168.10.104)配置/etc/keepalived/keepalived.conf

ini

global_defs {
    router_id r2  # 唯一路由ID
}

vrrp_script chk_haproxy {
    script "/etc/keepalived/chk.sh"
    interval 2
}

vrrp_instance VI_1 {
    state BACKUP
    interface ens33
    virtual_router_id 51
    priority 99  # 优先级低于Node1
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        192.168.10.100
    }
    track_script {
        chk_haproxy
    }
    notify_backup "/etc/init.d/haproxy restart"
    notify_fault "/etc/init.d/haproxy stop"
}

5.4 启动 Keepalived

bash

运行

systemctl restart keepalived
systemctl enable keepalived

5.5 验证 VIP

在 Node1 执行,查看 VIP 是否绑定:

bash

运行

ip a

显示192.168.10.100即配置成功。

六、集群高可用验证

6.1 基础连通性测试

通过VIP连接 MySQL,测试集群基础功能:

bash

运行

mysql -utest -p123456 -h192.168.10.100 -P3306

能正常登录表示架构连通正常。

6.2 MySQL 节点故障测试

  1. 关闭 Master1

bash

运行

systemctl stop mysqld
  1. 再次通过 VIP 连接 MySQL,依然可以正常访问,HAProxy 自动剔除故障节点。

6.3 HAProxy 节点故障测试

  1. 关闭 Node1 的 Keepalived

bash

运行

systemctl stop keepalived
  1. 查看 VIP,已自动漂移至 Node2(192.168.10.104)
  2. 业务连接无中断,实现无缝切换

6.4 数据同步验证

  1. 在 Master1 创建数据库:

sql

CREATE DATABASE test_ha;
  1. 在 Master2 查看,数据实时同步,双主功能正常。

七、常见问题排查

7.1 MySQL 连接报错(111)

plaintext

ERROR 2003 (HY000): Can't connect to MySQL server on 'IP:3306' (111)

表格

原因 解决方案
MySQL 仅监听本地 修改 my.cnf:bind-address=0.0.0.0
防火墙未关闭 执行关闭防火墙命令
MySQL 未启动 systemctl start mysqld

7.2 HAProxy 启动失败

报错:server 名称重复解决:同一listenserver名称必须唯一,如mysql1mysql2

7.3 Keepalived VIP 不漂移

  1. 检查网卡名称是否正确(ens33)
  2. 确认监控脚本chk.sh有执行权限
  3. 检查节点优先级配置正确
  4. 关闭防火墙与 SELinux

7.4 MySQL 主从同步失败

  1. 检查server-id是否唯一
  2. 确认复制用户myslave权限正常
  3. 检查节点网络连通性
  4. 重置主从同步:stop slave; reset slave;

八、架构总结

8.1 核心价值

  1. 全链路冗余:MySQL 双主 + HAProxy 双节点,无单点故障
  2. 自动故障转移:秒级切换,业务无感知
  3. 统一访问入口:VIP 屏蔽底层节点变化,业务无需修改配置
  4. 负载均衡:HAProxy 智能分发流量,提升集群性能

8.2 适用场景

  • 电商、金融、政务等核心业务数据库
  • 对可用性要求极高的生产系统
  • 需要水平扩展的 MySQL 集群

8.3 生产优化建议

  1. 配置读写分离:写请求主节点,读请求从节点
  2. 接入监控系统:Prometheus+Grafana 实时监控集群状态
  3. 定期数据备份:结合 xtrabackup 实现全量 + 增量备份
  4. 配置慢查询日志:优化 SQL,提升数据库性能
Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐