MySQL高可用

发布于:2025-05-17 ⋅ 阅读:(14) ⋅ 点赞:(0)

目录

一、引言

二、案例概述

2.1 MySQL 高可用概念

2.2 方案组成

2.3 方案优势

三、案例环境

3.1 环境规划

3.2 环境要求

四、MySQL 安装与配置

4.1 下载与编译安装 MySQL

4.2 初始化 MySQL

4.3 设定配置文件

4.4 配置 systemctl 方式启动

4.5 设置 root 用户密码

4.6 创建测试用户

五、配置 MySQL 双主复制

5.1 修改 Master1 配置文件

5.2 修改 Master2 配置文件

5.3 重启 MySQL 服务

5.4 给从服务器授权

5.5 查看主服务器状态

5.6 配置 Master1 作为 Master2 的从服务器

5.7 配置 Master2 作为 Master1 的从服务器

六、安装与配置 HAProxy

6.1 关闭 SELinux 和防火墙

6.2 安装 HAProxy

6.3 编辑 HAProxy 配置文件

6.4 检测配置文件并启动服务

6.5 测试 HAProxy 代理

七、安装与配置 Keepalived

7.1 关闭 SELinux 和防火墙

7.2 安装 Keepalived

7.3 编辑 Keepalived1 配置文件

7.4 编辑 Keepalived2 配置文件

7.5 添加监控脚本

7.6 启动 Keepalived 服务

7.7 测试 VIP 连接 MySQL

八、故障转移测试

8.1 模拟 Master1 节点故障

8.1.1 关闭 Master1 主机

8.1.2 验证 HAProxy 健康检查机制

8.1.3 验证 VIP 访问连续性

8.2 模拟 Keepalived1 节点故障

8.2.1 关闭 Keepalived1 服务

8.2.2 验证 VIP 漂移至 Keepalived2

8.2.3 验证业务连续性

8.3 模拟 Master2 节点故障(VIP 在 Keepalived2 上时)

8.3.1 关闭 Master2 主机

8.3.2 验证 HAProxy 自动切换至 Master1(假设 Master1 已恢复)

8.4 模拟双节点故障(极端场景)

8.4.1 关闭 Keepalived2 和 Master2

8.4.2 验证 VIP 漂移与服务降级

九、架构优化与扩展建议

9.1 读写分离配置(可选)

9.2 横向扩展 MySQL 节点

9.3 监控与告警


一、引言

在数字化时代,数据成为企业的核心资产,数据库的可靠性直接决定着业务的连续性。传统单节点 MySQL 架构存在单点故障风险,一旦宕机,会导致业务中断、数据丢失等严重后果。尤其在电商秒杀、金融交易等场景中,数据库的持续可用性(High Availability,HA)已成为系统设计的刚性需求。

为解决 MySQL 单点问题及应对日益增长的数据量带来的数据库压力,“MySQL 主主复制 + Keepalived+HAProxy” 这一经典高可用架构应运而生。该架构通过开源工具实现数据库的故障自动转移、负载均衡和读写分离,为企业提供高可用、高性能的数据库服务。本笔记将围绕该架构展开,详细介绍其理论知识与实践操作。

二、案例概述

2.1 MySQL 高可用概念

MySQL 高可用(High Availability)是指通过冗余设计,确保数据库服务在单节点故障、网络中断或硬件损坏等异常情况下,仍能持续对外提供服务,同时保证数据一致性。其核心目标是实现 “零停机、零数据丢失” 的业务连续性。

2.2 方案组成

“MySQL 主主复制 + Keepalived+HAProxy” 的高可用方案由三部分组成:

  1. MySQL 主主复制:两台 MySQL 实例互为主从,双向同步数据,均支持读写操作,提供冗余和扩展能力。
  2. Keepalived:通过 VRRP 协议管理虚拟 IP(VIP),监控 MySQL 状态,故障时自动将 VIP 漂移至存活节点,确保服务地址不变。
  3. HAProxy:作为反向代理和负载均衡器,将流量分发至 MySQL 节点,支持健康检查、读写分离(可选)和故障节点自动剔除。

2.3 方案优势

  1. 高可用性:Keepalived 实现秒级故障切换,HAProxy 健康检查确保流量仅路由到正常节点,避免单点故障。
  2. 读写扩展:主主架构支持双节点并发写入,提升写入性能;HAProxy 可配置读写分离,利用备节点分担读压力。
  3. 灵活扩展:可横向扩展 HAProxy 或 MySQL 节点,支持动态调整负载均衡策略(如轮询、权重)。
  4. 运维友好:基于开源工具,无厂商锁定,社区支持丰富,适合自建数据库集群。

三、案例环境

3.1 环境规划

主机 应用 操作系统 IP 地址
192.168.10.101 Master1 openEuler 24.03 MySQL 8
192.168.10.102 Master2 openEuler 24.03 MySQL 8
192.168.10.103 Keepalived1、HAProxy openEuler 24.03 -
192.168.10.104 Keepalived2、HAProxy openEuler 24.03 -

3.2 环境要求

  • 所有节点关闭 SELinux 和防火墙,确保网络通信正常。
  • 安装必要的依赖包,如 gcc、make 等,以便编译安装软件。

四、MySQL 安装与配置

4.1 下载与编译安装 MySQL

  1. 从 MySQL 官方网站下载适合 openEuler 系统的 MySQL 8 源码包。
  2. 解压源码包:
tar -xvf mysql-8.0.36.tar.gz

  1. 创建 MySQL 用户和组:
groupadd mysql
useradd -r -g mysql -s /bin/false mysql

  1. 编译配置(在源码目录下执行):
cmake -DCMAKE_INSTALL_PREFIX=/usr/local/mysql -DMYSQL_UNIX_ADDR=/usr/local/mysql/data/mysql.sock -DDEFAULT_CHARSET=utf8 -DDEFAULT_COLLATION=utf8_general_ci -DWITH_INNOBASE_STORAGE_ENGINE=1 -DWITH_PARTITION_STORAGE_ENGINE=1 -DWITH_FEDERATED_STORAGE_ENGINE=1 -DWITH_BLACKHOLE_STORAGE_ENGINE=1 -DWITH_MYISAM_STORAGE_ENGINE=1 -DENABLED_LOCAL_INFILE=1 -DMYSQL_DATADIR=/usr/local/mysql/data -DSYSCONFDIR=/etc -DMYSQL_TCP_PORT=3306 -DENABLE_DOWNLOADS=1 -DDEFAULT_AUTHENTICATION_PLUGIN=mysql_native_password

  1. 编译并安装:
make -j$(nproc)
make install

4.2 初始化 MySQL

  1. 创建数据目录并设置权限:
mkdir -p /usr/local/mysql/data
chown -R mysql:mysql /usr/local/mysql

  1. 初始化数据库(在 /usr/local/mysql/bin 目录下执行):
./mysqld --initialize --user=mysql --basedir=/usr/local/mysql --datadir=/usr/local/mysql/data

此次初始化没有采用无密码模式,因此会生成初始随机密码,需要保存,用以后续登录 MySQL 数据库使用。例如,输出中可能显示类似 “A temporary password is generated for root@localhost: Xr6:Gg*u8?/8” 的信息,记录该密码。

4.3 设定配置文件

编辑 MySQL 的配置文件 /etc/my.cnf,内容如下:

[client]
socket=/usr/local/mysql/data/mysql.sock
[mysqld]
socket=/usr/local/mysql/data/mysql.sock
bind-address = 0.0.0.0
skip-name-resolve
port = 3306
basedir=/usr/local/mysql
datadir=/usr/local/mysql/data
max_connections=2048
character-set-server=utf8
default-storage-engine=INNODB
max_allowed_packet=16M

4.4 配置 systemctl 方式启动

  1. 将 MySQL 添加成为系统服务,通过使用 systemctl 来管理。在 /usr/local/mysql/support-files 目录下找到 mysql.server 文件,将其复制到 /etc/rc.d/init.d 目录下,改名为 mysqld 并赋予可执行权限:
cp /usr/local/mysql/support-files/mysql.server /etc/rc.d/init.d/mysqld
chmod +x /etc/rc.d/init.d/mysqld

  1. 编辑生成 mysqld.service 服务,通过 systemctl 方式来管理。编辑 /lib/systemd/system/mysqld.service 文件,内容如下:
[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

  1. 重新加载 systemd 配置:
systemctl daemon-reload

  1. 启用并启动 MySQL 服务:
systemctl enable mysqld
systemctl start mysqld

  1. 检查 MySQL 服务是否启动成功,查看 3306 端口是否监听:
netstat -tunlp | grep 3306

4.5 设置 root 用户密码

使用初始随机密码登录 MySQL,然后设置新密码:

mysqladmin -u root -p password 'pwd123'

输入初始随机密码完成密码修改。

4.6 创建测试用户

在 Master1 和 Master2 上都执行以下操作,创建测试用户 test,用于后续验证实验:

mysql -u root -p
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;

由于 MySQL 8.0 默认使用 caching_sha2_password 认证插件,将其替换为 mysql_native_password 旧版认证插件,确保从库能兼容。

五、配置 MySQL 双主复制

5.1 修改 Master1 配置文件

在 Master1 的 /etc/my.cnf 中修改或增加以下内容:

log-bin=/usr/local/mysql/data/mysql-bin #启用二进制日志并指定其存储路径
binlog_format=MIXED #定义二进制日志的记录格式为混合模式
server-id=1 #为mysql实例分配一个唯一的服务器标识符

5.2 修改 Master2 配置文件

在 Master2 的 /etc/my.cnf 中修改或增加以下内容:

log-bin=/usr/local/mysql/data/mysql-bin #启用二进制日志并指定其存储路径
binlog_format=MIXED #定义二进制日志的记录格式为混合模式
server-id=2 #为mysql实例分配一个唯一的服务器标识符

5.3 重启 MySQL 服务

在 Master1 和 Master2 上都执行以下命令重启 MySQL 服务:

systemctl restart mysqld

5.4 给从服务器授权

在 Master1 和 Master2 上都执行以下操作,创建用于复制的用户 myslave 并授权:

mysql -u root -p
CREATE USER 'myslave'@'192.168.10.%' IDENTIFIED BY '123456';
GRANT REPLICATION SLAVE ON *.* TO 'myslave'@'192.168.10.%';
ALTER USER 'myslave'@'192.168.10.%' IDENTIFIED WITH mysql_native_password BY '123456';
FLUSH PRIVILEGES;

同样,将认证插件替换为 mysql_native_password 以兼容从库。

5.5 查看主服务器状态

在 Master1 上登录 MySQL,执行以下命令查看主服务器状态:

show master status;

记录下 File 列的日志名(如 mysql-bin.000001)和 Position 列的偏移量(如 157),这两个值在配置从服务器时需要。

5.6 配置 Master1 作为 Master2 的从服务器

在 Master2 上登录 MySQL,执行以下命令配置同步,将 master_log_file 和 master_log_pos 参数替换为 Master1 的实际值:

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;

然后查看 Slave 状态,确保 Slave_IO_Running 和 Slave_SQL_Running 都为 YES:

mysql -uroot -p -e "show slave status \G" | grep Yes

5.7 配置 Master2 作为 Master1 的从服务器

在 Master1 上登录 MySQL,执行以下命令配置同步,将 master_log_file 和 master_log_pos 参数替换为 Master2 的实际值(假设 Master2 的主服务器状态中 File 和 Position 与 Master1 相同,实际操作中需根据 Master2 的 show master status 结果调整):

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;

同样查看 Slave 状态,确保两个值为 YES。

六、安装与配置 HAProxy

6.1 关闭 SELinux 和防火墙

在 Keepalived1 和 Keepalived2 上都执行以下命令:

sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config
setenforce 0
systemctl disable firewalld
systemctl stop firewalld

6.2 安装 HAProxy

使用 dnf 命令安装 HAProxy:

dnf install haproxy

6.3 编辑 HAProxy 配置文件

在 Keepalived1 和 Keepalived2 上都编辑 /etc/haproxy/haproxy.cfg 文件,内容如下(红色标注为关键配置):

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
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 http-keep-alive 5s
timeout check 5s
maxconn 3000
listen mysql
bind 0.0.0.0:3306 #显式指定监听地址和端口
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

配置说明:

  • mode tcp:表示 TCP 代理。
  • listen mysql 0.0.0.0:3306:创建一个名为 mysql 的监听服务,绑定到所有网卡的 3306 端口(MySQL 默认端口),作为流量入口。
  • balance leastconn:指定使用最少连接数算法分配请求,将新连接导向当前活跃连接最少的后端服务器,避免单点过载。
  • server 声明两个 MySQL 服务器节点 mysql1 和 mysql2,分别指向 192.168.10.101:3306 和 192.168.10.102:3306。check port 3306 表示通过检查节点的 3306 端口是否响应,判断其存活状态;maxconn 300 限制每个后端节点的最大并发连接数为 300,防止节点被压垮。

6.4 检测配置文件并启动服务

  1. 检测 HAProxy 配置文件是否正确:
haproxy -c -f /etc/haproxy/haproxy.cfg

  1. 重启 HAProxy 服务:
systemctl restart haproxy

6.5 测试 HAProxy 代理

使用测试用户 test,通过 HAProxy 的代理端口登录 MySQL,验证 HAProxy 是否正常工作:

mysql -utest -p123456 -h192.168.10.103 -P3306

如果能成功登录,说明 HAProxy 代理配置正确。

七、安装与配置 Keepalived

7.1 关闭 SELinux 和防火墙

在 Keepalived1 和 Keepalived2 上都执行与 HAProxy 安装时相同的关闭 SELinux 和防火墙的命令。

7.2 安装 Keepalived

使用 dnf 命令安装 Keepalived:

dnf install keepalived

7.3 编辑 Keepalived1 配置文件

在 Keepalived1 上编辑 /etc/keepalived/keepalived.conf 文件,内容如下(红色标注为关键配置,与 Keepalived2 不同之处需注意):

! Configuration File for keepalived
global_defs {
router_id r1
}
vrrp_script chk_haproxy {
script "/etc/keepalived/chk.sh"
interval 2
}
vrrp_instance VI_1 {
state BACKUP
nopreempt #启用非抢占模式
interface ens33 #指定网络接口
virtual_router_id 51 #虚拟路由ID,同一VRRP实例需一致
priority 100 #优先级,数值越大优先级越高
advert_int 1 #通告间隔时间(秒)
authentication {
auth_type PASS
auth_pass 1111 #认证密码,同一VRRP实例需一致
}
virtual_ipaddress {
192.168.10.100 #虚拟IP地址
}
track_script {
chk_haproxy #关联监控脚本
}
notify_backup "/etc/init.d/haproxy restart" #当状态变为BACKUP时执行的命令
notify_fault "/etc/init.d/haproxy stop" #当检测到故障时执行的命令
}

启用 nopreempt 的作用是:节点 A(优先级 100,配置 nopreempt)故障→节点 B 成为 Master;节点 A 恢复→不触发抢占,节点 B 继续作为 Master,VIP 不切换;仅当节点 B 故障时,节点 A 才会重新成为 Master。

7.4 编辑 Keepalived2 配置文件

在 Keepalived2 上编辑 /etc/keepalived/keepalived.conf 文件,与 Keepalived1 的区别在于 router_id 和 priority:

! Configuration File for keepalived
global_defs {
router_id r2
}
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 #优先级低于Keepalived

7.5 添加监控脚本

在 Keepalived1 和 Keepalived2 上均需创建并编辑监控脚本chk.sh,用于检测 HAProxy 进程是否存活:

vim /etc/keepalived/chk.sh

脚本内容如下:

#!/bin/bash  
# 检查HAProxy进程数量  
if [ $(ps -C haproxy --no-header | wc -1) -eq 0 ]; then  
    # 若进程不存在,停止Keepalived服务(触发VIP漂移)  
    /etc/init.d/keepalived stop  
fi  

赋予脚本执行权限:

chmod +x /etc/keepalived/chk.sh

7.6 启动 Keepalived 服务

在 Keepalived1 和 Keepalived2 上分别启动服务:

systemctl start keepalived

首次启动时,由于两者均配置为BACKUP且 Keepalived1 优先级更高(100 vs 99),VIP(192.168.10.100)会先绑定在 Keepalived1 的ens33接口上。可通过以下命令验证:

# 在Keepalived1上执行  
ip a | grep ens33  
# 输出应包含虚拟IP:192.168.10.100/32  

7.7 测试 VIP 连接 MySQL

使用测试用户通过 VIP 连接 MySQL,验证负载均衡是否正常:

mysql -utest -p123456 -h192.168.10.100 -P3306  

若能成功登录,说明 Keepalived 与 HAProxy 已协同工作,流量通过 VIP 转发至后端 MySQL 节点。

八、故障转移测试

8.1 模拟 Master1 节点故障

8.1.1 关闭 Master1 主机
# 在Master1所在主机执行(假设为物理机或虚拟机操作)  
shutdown -h now  
8.1.2 验证 HAProxy 健康检查机制
  • 检测 Master1 状态
    # 在Keepalived1或Keepalived2上执行  
    mysql -utest -p123456 -h192.168.10.103 -P3306  # 通过HAProxy IP连接  
    mysql> SHOW PROCESSLIST;  # 查看连接节点,应仅显示Master2  
    
  • 原理:HAProxy 通过check port 3306定期探测节点状态,发现 Master1 离线后,会自动将其从负载列表中剔除,流量仅转发至 Master2。
8.1.3 验证 VIP 访问连续性
ping 192.168.10.100  # VIP应保持可达  
mysql -utest -p123456 -h192.168.10.100 -P3306  # 仍可通过VIP登录  

8.2 模拟 Keepalived1 节点故障

8.2.1 关闭 Keepalived1 服务
systemctl stop keepalived  # 在Keepalived1上执行  
8.2.2 验证 VIP 漂移至 Keepalived2
  • 查看 Keepalived2 的 IP 地址
    # 在Keepalived2上执行  
    ip a | grep ens33  
    # 应显示VIP已绑定:192.168.10.100/32  
    
  • 原理:Keepalived 通过 VRRP 协议检测到主节点(Keepalived1)离线后,优先级次高的 Keepalived2 会接管 VIP,确保 HAProxy 服务地址不变。
8.2.3 验证业务连续性
mysql -utest -p123456 -h192.168.10.100 -P3306  # 仍可通过VIP登录,流量经Keepalived2的HAProxy转发至Master2  

8.3 模拟 Master2 节点故障(VIP 在 Keepalived2 上时)

8.3.1 关闭 Master2 主机
shutdown -h now  # 在Master2所在主机执行  
8.3.2 验证 HAProxy 自动切换至 Master1(假设 Master1 已恢复)
  • 前提:若 Master1 之前故障后已恢复,HAProxy 会重新检测到其存活并加入负载列表。
  • 验证连接
    mysql -utest -p123456 -h192.168.10.100 -P3306  
    mysql> SELECT @@server_id;  # 应返回1(Master1的server-id)  
    

8.4 模拟双节点故障(极端场景)

8.4.1 关闭 Keepalived2 和 Master2
# 在Keepalived2上执行  
systemctl stop keepalived  
# 在Master2上执行  
systemctl stop mysqld  
8.4.2 验证 VIP 漂移与服务降级
  • 若 Keepalived1 已恢复:VIP 会重新漂移至 Keepalived1,HAProxy 继续转发流量至存活的 Master1。
  • 若 Master1 也故障:整个集群不可用,需人工介入恢复(如启动备用节点或故障修复)。

九、架构优化与扩展建议

9.1 读写分离配置(可选)

HAProxy 支持根据 SQL 语句类型(读 / 写)分发流量,减轻主节点压力:

  1. 修改 HAProxy 配置文件,新增读负载均衡监听:
    listen mysql_read  
    bind 0.0.0.0:3307  
    mode tcp  
    balance leastconn  
    server mysql1 192.168.10.101:3306 check port 3306 maxconn 300 read-only  
    server mysql2 192.168.10.102:3306 check port 3306 maxconn 300 read-only  
    
  2. 应用层配置:读请求连接 3307 端口,写请求连接 3306 端口。

9.2 横向扩展 MySQL 节点

  1. 新增从节点
    • 在新节点上配置为任一主节点的从库(参考双主复制步骤)。
    • 更新 HAProxy 配置,添加新节点:
      server mysql3 192.168.10.105:3306 check port 3306 maxconn 300  
      
  2. 扩展 Keepalived+HAProxy 节点
    • 增加 Keepalived 备份组,提升高可用层冗余。
    • 使用 DNS 轮询或 LVS 负载均衡 HAProxy 节点,避免 HAProxy 单点。

9.3 监控与告警

  • 基础监控
    • 使用 Prometheus+Grafana 监控 MySQL 指标(如 QPS、连接数、复制延迟)。
    • 监控 Keepalived 的 VIP 状态和 HAProxy 的节点健康度。
  • 告警规则
    • 复制延迟超过阈值时触发告警。
    • HAProxy 节点故障或 VIP 漂移时发送通知。