Mysql 高可用
什么是 MySQL 的高可用?
MySQL 高可用(High Availability,简称 HA)是指通过技术架构设计与部署,确保数据库系统在面临硬件故障、软件异常、人为失误或网络问题时,仍能持续提供服务、避免数据丢失,并将停机时间降至最低的解决方案。其核心目标是通过冗余节点部署和自动故障转移机制,解决单节点数据库的 “单点故障” 问题,满足企业对服务连续性和数据可靠性的严格要求。
高可用的核心技术特征:
- 多节点冗余:至少部署两个数据库节点(如主从、集群),数据实时同步或异步复制。
- 自动故障检测与切换:通过监控工具(如 MHA、Orchestrator、InnoDB Cluster 等)实时检测主节点状态,故障时自动将备用节点提升为新主节点。
- 数据一致性保障:通过同步复制、半同步复制或分布式协议(如 Paxos)确保多节点数据一致。
MySQL 高可用的核心优点:
一、大幅提升服务可用性,减少业务中断
- 低停机时间(低 RTO):
传统单节点数据库故障可能导致数小时停机,而高可用架构可将故障切换时间缩短至秒级甚至毫秒级。例如,电商平台在大促期间主节点宕机时,高可用方案可自动切换至从节点,确保订单系统不中断。 - 7×24 小时持续运行:
通过多节点冗余(如一主多从、双主架构),即使部分节点故障,剩余节点仍可支撑业务,满足企业级系统对可用性的严格要求(如 99.99% 可用性目标,年停机时间仅约 52 分钟)。
二、增强数据安全性,降低数据丢失风险
- 多副本冗余保护:
数据同时存在于多个节点,避免单节点硬件故障(如磁盘损坏)导致数据永久丢失。例如,误删除表后,可通过从节点快速恢复数据。 - 低数据丢失率(低 RPO):
通过同步复制(事务提交需主从节点均写入日志)或半同步复制(至少一个从节点确认接收日志),将数据丢失量(RPO)降至接近 0。金融场景中,此机制可确保交易数据不丢失。
三、提升系统性能与扩展性
-
读写分离与负载均衡
主从架构中,读请求可分发到从节点,减轻主节点压力,支持更高并发。例如:
-- 应用层将读请求路由到从库(主库处理写请求) SELECT * FROM users WHERE id=1; -- 读操作走从库 INSERT INTO orders VALUES (...); -- 写操作走主库
-
横向扩展能力:
可通过添加从节点或分片节点(如分库分表)应对业务增长,避免单机性能瓶颈。例如,社交平台用户量激增时,可新增从节点承担读压力。
四、支持无中断运维与版本升级
- 在线维护能力:
进行数据库升级、参数调整或硬件更换时,可先将节点下线维护,完成后重新加入集群,全程不影响业务。例如,从节点升级 MySQL 版本时,主节点仍正常提供服务,升级后切换角色即可。 - 热备与快速恢复:
从节点可作为热备节点,无需停机即可备份数据,或在主节点故障时直接接管服务,大幅缩短恢复时间。
五、降低企业风险与成本
- 避免业务损失:
金融、医疗等场景中,数据库故障可能导致交易失败、病历数据丢失等严重后果,高可用架构可有效规避此类风险。 - 减少运维成本:
自动化故障切换减少人工干预,降低运维复杂度;多节点冗余可复用硬件资源(如从节点兼作查询节点),提升资源利用率。
六、灵活应对多种故障场景
- 硬件故障:服务器宕机、磁盘损坏时,自动切换至其他节点。
- 网络故障:主从网络中断时,通过半同步机制确保数据一致性,网络恢复后自动重连。
- 人为失误:误操作(如删库)可通过从节点回滚或集群多副本机制恢复。
总结:高可用的核心价值
MySQL 高可用通过 “冗余 + 自动切换 + 负载均衡” 的设计,在可用性、数据安全、性能扩展、运维效率四个维度实现突破,是企业级数据库部署的基础需求。其本质是通过技术架构解决 “单点故障” 问题,让数据库服务像水电一样稳定可靠,支撑核心业务持续运行。
实例
环境准备
系统 | 描述 |
---|---|
openEuler 24.3 :192.168.10.101 | mysql 8 |
openEuler 24.3 :192.168.10.102 | mysql 8 |
keepalived+haproxy 192.168.10.103 | |
keepalived+haproxy 192.168.10.104 | |
客户端 | 192.168.10.105 |
mysql做主主互为复制
此操作在两台mysql上面操作
更改配置文件两台都要改 server-id不能一样
[client]
# 客户端连接 MySQL 时使用的 Unix 套接字文件路径
socket=/usr/local/mysql/data/mysql.sock
[mysqld]
# 服务器端使用的 Unix 套接字文件路径,必须与客户端一致
socket=/usr/local/mysql/data/mysql.sock
# 绑定所有可用的网络接口,允许外部主机连接
bind-address = 0.0.0.0
# 禁用反向 DNS 解析,提高连接性能
skip-name-resolve
# MySQL 服务监听的端口号
port = 3306
# MySQL 安装根目录
basedir=/usr/local/mysql
# 数据库文件存储目录
datadir=/usr/local/mysql/data
# 最大允许的并发连接数
max_connections=2048
# 服务器默认字符集
character-set-server=utf8
# 默认存储引擎(推荐使用 InnoDB)
default-storage-engine=INNODB
# 允许的最大数据包大小(影响大事务和大文件导入)
max_allowed_packet=16M
# 启用二进制日志(用于主从复制和数据恢复)
log-bin=/usr/local/mysql/data/mysql-bin
# 二进制日志格式(混合模式,结合了 STATEMENT 和 ROW 的优点)
binlog-format=MIXED
# 服务器唯一标识(主从复制中必须配置,且每个服务器不同)
server-id=1
[mysqld_safe]
# MySQL 安全启动脚本的错误日志路径
log-error=/usr/local/mysql/data/error.log
# 注释掉的 PID 文件路径(可能是从 MariaDB 配置继承而来)
#pid-file=/var/run/mariadb/mariadb.pid
进入mysql
注意!!!两台mysql互为复制互为主从 pos使用对方的
-- 创建用于复制的用户'myslave',允许从192.168.10网段的任意IP连接
-- 密码为123456(生产环境建议使用更复杂的密码)
mysql> create user 'myslave'@'192.168.10.%' identified by '123456';
Query OK, 0 rows affected (0.01 sec)
-- 授予用户复制权限(REPLICATION SLAVE),该权限允许从服务器读取主服务器的二进制日志
mysql> grant replication slave on *.* to 'myslave'@'192.168.10.%';
Query OK, 0 rows affected (0.01 sec)
-- 修改用户认证方式为mysql_native_password
-- 确保旧版本客户端或驱动(如Python的mysql-connector)能正常连接
mysql> alter user 'myslave'@'192.168.10.%' identified with mysql_native_password by '123456';
Query OK, 0 rows affected (0.00 sec)
-- 查看主服务器当前二进制日志状态
-- File: 当前使用的二进制日志文件名
-- Position: 日志文件中的位置(复制起始点)
-- 后续配置从服务器时需使用这些值
mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000001 | 1014 | | | |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
-- 刷新权限,确保新权限立即生效
mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)
-- 配置从服务器连接主服务器的参数(此命令应在从服务器上执行!)
-- 注意:主主互为复制这里使用令一台mysql的pos
mysql> change master to
master_user='myslave', -- 复制用户
master_host='192.168.10.102', -- 主服务器IP(假设102是主服务器)
master_log_file='mysql-bin.000001', -- 主服务器当前二进制日志文件
master_log_pos=1180, -- 主主互为复制这里使用令一台mysql的pos
master_password='123456'; -- 复制用户密码
Query OK, 0 rows affected, 8 warnings (0.01 sec)
启用同步在两台mysql上都看到 ioyes sqlyes
mysql> start slave ###启用slave
-> ;
Query OK, 0 rows affected, 1 warning (0.01 sec)
mysql> show slave status \G ####查看我的信息
*************************** 1. row ***************************
Slave_IO_State: Waiting for source to send event
Master_Host: 192.168.10.101
Master_User: myslave
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000001
Read_Master_Log_Pos: 1181
Relay_Log_File: mysql2-relay-bin.000002
Relay_Log_Pos: 493
Relay_Master_Log_File: mysql-bin.000001
Slave_IO_Running: Yes ######io线程OK
Slave_SQL_Running: Yes ######sql线程ok
Replicate_Do_DB: .............
安装haproxy 服务器做负载均衡器使用
yum -y install haproxy ###安装haproxy
编辑haproxy的配置文件
两台都一样
#---------------------------------------------------------------------
# HAProxy 全局配置
# 控制 HAProxy 进程整体行为的参数
#---------------------------------------------------------------------
global
log 127.0.0.1 local2 # 将日志发送到本地syslog服务器,使用local2设施
chroot /var/lib/haproxy # 改变进程根目录增强安全性
pidfile /var/run/haproxy.pid # 进程ID文件位置
user haproxy # 运行HAProxy的用户
group haproxy # 运行HAProxy的用户组
daemon # 以守护进程模式运行
maxconn 4000 # 全局最大并发连接数限制
#---------------------------------------------------------------------
# 默认配置段
# 为后续所有配置提供默认参数
#---------------------------------------------------------------------
defaults
mode tcp # 工作在TCP模式(不解析HTTP协议)
log global # 使用global段定义的日志配置
option tcplog # 启用TCP日志记录完整连接信息
option dontlognull # 不记录空连接
retries 3 # 连接失败后的重试次数
timeout http-request 5s # HTTP请求超时(在TCP模式下可能不需要)
timeout queue 1m # 队列中等待的最长时间
timeout connect 5s # 连接到后端服务器的超时时间
timeout client 1m # 客户端连接超时时间
timeout server 1m # 服务器连接超时时间
timeout http-keep-alive 5s # HTTP keep-alive超时(在TCP模式下可能不需要)
timeout check 5s # 健康检查超时时间
maxconn 3000 # 每个进程的最大连接数限制
#---------------------------------------------------------------------
# MySQL负载均衡配置
#---------------------------------------------------------------------
listen mysql
bind 0.0.0.0:3306 # 监听所有IP的3306端口(MySQL默认端口)
balance leastconn # 使用最少连接数算法进行负载均衡
server mysql1 192.168.10.101:3306 check port 3306 maxconn 300 # 第一个MySQL服务器
server mysql2 192.168.10.102:3306 check port 3306 maxconn 300 # 第二个MySQL服务器
检查并启动服务
[root@hk1 ~]# haproxy -c -f /etc/haproxy/haproxy.cfg ###检查配置文件是否有误
[root@hk1 ~]# systemctl start haproyx ###启动haproxy服务
使用一个测试用户test访问haproxy的代理端口号登录mysql
[root@bogon ~]# mysql -utest -ppwd123 -h192.168.10.103 -P3306 ###登录代理服务器测试代理是否成功
[root@bogon ~]# mysql -utest -ppwd123 -h192.168.10.103 -P3306
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 21
Server version: 8.0.36 MySQL Community Server - GPL
Copyright (c) 2000, 2025, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql>
安装keepalived做高可用
在两台haproxy服务器上安装keepalived
以下操作在两台keepalived上都要执行
[root@hk1 ~]# dnf -y install keepalived
优先级高就是master global可以理解为标识符 router-id同一vrrp组必须是一样的
# Configuration File for keepalived
# 此配置用于实现HAProxy的高可用,通过VRRP协议实现IP漂移
# 全局定义部分
global_defs {
router_id r1 # 定义路由标识,用于唯一标识此Keepalived实例
}
# VRRP监控脚本定义
vrrp_script chk_haproxy {
script "/etc/keepalived/chk.sh" # 指定监控脚本路径,用于检查HAProxy状态
interval 2 # 检查间隔为2秒
}
# VRRP实例配置
vrrp_instance VI_1 {
state BACKUP # 初始状态为BACKUP,避免启动时抢占
nopreempt # 非抢占模式,避免优先级波动导致的IP漂移
interface ens160 # 使用的网络接口名
virtual_router_id 51 # 虚拟路由ID,同一VRRP组必须相同
priority 100 # 当前实例优先级,值越大越优先成为MASTER
advert_int 1 # VRRP通告间隔为1秒
authentication { # 认证配置,确保VRRP通信安全
auth_type PASS # 密码认证方式
auth_pass 1111 # 认证密码
}
virtual_ipaddress { # 定义虚拟IP地址
192.168.10.100 # 对外提供服务的VIP
}
track_script { # 跟踪监控脚本
chk_haproxy # 引用上面定义的监控脚本
}
# 状态转换通知脚本
notify_backup "/etc/init.d/haproxy restart" # 转为BACKUP状态时重启HAProxy
notify_fault "/etc/init.d/haproxy stop" # 转为FAULT状态时停止HAProxy
}
添加监控脚本并启动keepalived服务
该脚本放在keepalived配置文件下
#!/bin/bash
# Keepalived监控脚本:检测HAProxy状态并在服务异常时自动切换
# 检查haproxy进程是否存在(-C参数直接通过进程名查找)
if [ $(ps -C haproxy --no-header | wc -l) -eq 0 ]; then
# 如果haproxy进程不存在(计数为0),则停止当前节点的keepalived服务
# 触发VRRP协议将VIP自动切换到其他备份节点
/etc/init.d/keepalived stop
fi
使用ip a 查看vip在优先级高的服务器上
[root@hk1 keepalived]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host noprefixroute
valid_lft forever preferred_lft forever
2: ens160: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether 00:0c:29:0e:ce:c8 brd ff:ff:ff:ff:ff:ff
inet 192.168.10.103/24 brd 192.168.10.255 scope global noprefixroute ens160
valid_lft forever preferred_lft forever
inet 192.168.10.100/32 scope global ens160
valid_lft forever preferred_lft forever
inet6 fe80::20c:29ff:fe0e:cec8/64 scope link noprefixroute
valid_lft forever preferred_lft forever
客户端访问vip 连接后端mysql服务器
[root@bogon ~]# mysql -utest -ppwd123 -h192.168.10.100 -P3306
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 22
Server version: 8.0.36 MySQL Community Server - GPL
Copyright (c) 2000, 2025, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql>
当第一台keepalived服务器关闭时 第二台keepalived服务器 vip会漂移到第二台keepalived服务器上
[root@hk ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host noprefixroute
valid_lft forever preferred_lft forever
2: ens160: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether 00:0c:29:4b:2c:33 brd ff:ff:ff:ff:ff:ff
inet 192.168.10.104/24 brd 192.168.10.255 scope global noprefixroute ens160
valid_lft forever preferred_lft forever
inet 192.168.10.100/32 scope global ens160
valid_lft forever preferred_lft forever
inet6 fe80::20c:29ff:fe4b:2c33/64 scope link noprefixroute
valid_lft forever preferred_lft forever