目录
一:案例概述
1.案例前置知识点
1.1什么是MySQL高可用
1.2方案组成
1.3优势
2.案例环境
2.1本案例环境
2.2案例需求
2.3案例实现思路
二:案例实施
1.安装MySQL数据库
(1)基础环境准备
(2)二进制安装
(3)设定配置文件
(4)配置systemctl方式启动
(5)登录MySQL程序,创建测试用户,后续验证实验时使用。(Master1,Master2都执行)
2.配置MySQL双主复制
(1)在Master1 /etc/my.cnf 中修改或增加下面内容
(2)Master2 /etc/my.cnf 中修改或增加下面内容
(3)重启MySQL服务。(Masterl、Master2都执行)
(4)登录MySQL程序,给从服务器授权。(Masterl、Master2都执行)
(5)登录MySQL,配置同步。(Masterl、Master2都执行)
3.安装haproxy
(1)关闭SELinux和防火墙
(2)安装 haproxy
(3)编辑haproxy配置文件
(4)检测配置文件,并启动服务
(5)测试
4.安装keepalived
(1)关闭SELinux和防火墙
(2)安装keepalived
(3)编辑haproxy配置文件
(4)编测试使用VIP连接mysql
5.测试故障转移
1.关闭masterl主机,测试使用vip能否正常访问mysql数据库
2.接着关闭keepalivedl,测试使用vip能否正常访问mysql 据库
目前MySQL已经成为市场上主流数据库之一,考虑到业务的重要性,MySQL数据库单点问题已成为企业网站架构中最大的隐患。随着技术的发展,MHA的出现就是解决MySQL单点的问题。另外随着企业数据量越来越庞大大,数据库的压力又成为企业的另一个瓶颈,MySQL多主多从架构的出现可以减轻MySQL本身的压力。本章将主要围绕"MySQL主主复制+Keepalived+HAProxy"这一经典高可用架构展开,通过理论结合实践,解析如何通过开源工具实现数据库的故障自动转移、负载均衡和读写分离。
MySQL高可用(HighAvailability)是指通过冗余设计,确保数据库服务在单节点故障、网络中断或硬件损坏等异常情况下,仍能持续对外提供服务,同时保证数据一致性。其核心目标是实现"零停机、零数据丢失"的业务连续性。
MySQL主主复制+Keepalived+HAProxy的高可用方案日由三部分组成
MySQL主主复制:两台MySQL实例互为主从,双向同步数据,均支持读写操作,提供冗余和扩展能力。
Keepalived:通过VRRP协议管理虚拟 IP(VIP),监控MySQI状态,故障时自动将VIP漂移至存活节点,确保服务地址不变。
HAProxy:作为反向代理和负载均衡器,将流量分发至MySQL 节点,支持健康检查、读写分离(可选)和故障节点自动剔除。
高可用性:Keepalived实现秒级故障切换,HAProxy健康检查确保流量仅路由到正常节点,避免单点故障。
读写扩展:主主架构支持双节点并发写入,提升写入性能;HAProxxy可配置读写分离,利用备节点分担读压力。
灵活扩展:可横向扩展HAProxy或MySQL节点,支持动态调整负载均衡策略(如轮询、权重)。
运维友好基于开源工具,无厂商锁定,社区支持丰富,适合自建数据库集群。
主机 | 操作系统 | IP地址 | 应用 |
Master1 | openEuler 24.03 | 192.168.10.101 | MySQL8 |
Master2 | openEuler 24.03 | 192.168.10.102 | MySQL8 |
keepalived1 | openEuler 24.03 | 192.168.10.103 | keeplived、haproxy |
keepalived2 | openEuler 24.03 | 192.168.10.104 | keeplived、haproxy |
本案例要求通过MHA监控MySQL数据库在故障时进行自动切换,不影响业务。
(1)安装MySQL数据库;
(2)配置MySQL互为主从;
(3)安装haproxy软件并配置复制均衡;
(4)安装keepalived软件并配置故障转移;
(5)模拟master故障切换
在Masterl、Master2服务器上安装 MySQL数据库。本案例采用二进制安装
如果采用OpenEulerminimal安装的系统,在使用前需要安装一些基础软件包工具。
[root@localhost~]# yum -y install gcc vim wget net-tools lrzsz
安装MySQL依赖的软件包
[root@localhost~]# dnf install -у libaio numactl openssl ncurses-compat-libs
创建运行MySQL程序的用户
[root@localhost~]# useradd -M -s /sbin/nologin mysql关闭SELinux和防火墙
[root@localhost~]# sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config
[root@localhost~]# setenforce 0
[root@localhost~]# systemctl disable firewalld
[root@localhost~]# systemctl stop firewalld
二进制安装的版本采用跟上面编译安装的版本一样MySQL 80.36。首先需要下载该软件包或者提前上传,然后再解压进行配置。
[root@localhost~]# tar xJf mysql-8.0.36-linux-glibc2.28-x86_64.tar.xz
[root@localhost~]# mv mysql-8.0.36-linux-glibc2.28-x86_64 /usr/local/mysql
[root@localhost~]# mkdir /usr/local/mysql/data
[root@localhost~]# chown -R mysql.mysql /usr/local/mysql/data
[root@localhost~]# cd /usr/local/mysql/bin
[root@localhost~]# ./mysqld --initialize --user=mysql --basedir=/usr/local/mysql --datadir=/usr/local/mysq/data会生成一个临时密码
password is generated for root@localhost: Xr6:Gg*u8?/8
MySQL的配置文件跟上面编译安装的配置文件类似。
[root@localhost~]# vim /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将MySQL的可执行文件写入环境变量中。
[root@localhost~]# echo "export PATH=$PATH:/usr/local/mysql/bin /etc/profile
[root@localhost~]#./etc/profile //使配置在当前Shell中生效
将MySQL添加成为系统服务,通过使用systemctl来管理。在/usr/local/mysql/support-files 目录下找到 mysql.server文件,将其复制到/etc/rc.d/init.d目录下,改名为mysqld并赋予可执行权限
[root@localhost ~้]# cp /usr/local/mysql/support-files/mysql.server /etc/rc.d/init.d/mysqld
[root@localhost~]# chmod +x /etc/rc.d/init.d/mysqld编辑生成mysqld.service服务,通过systemctl方式来管理
[root@localhost~]# vim /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
[root@localhost~]# systemctl daemon-reload
[root@localhost~]# systemctl enable mysqld
[root@localhost~]# systemctl start mysqld
[root@localhost~]# netstat -tunlp grep 3306
[root@localhost ^]#mysql -u root -p
mysql>CREATE USER 'test' @ 192.168.10.%'IDENTIFIED BY '123456';
Query OK, 0 rows affected (0.01 sec)
mysql> GRANT ALL ON *. * TO 'test'@'192.168.10.%';
Query OK, O rows affected (0.01 sec)
mysql>ALTER USER test' @'192.168.10. % IDENTIFIED WITH mysql_native_password BY '123456' ;
#MySQL 8.0默认使用caching_sha2_password 认 i证插件,将mysql_native_password替换为旧版认证插件,确保从库能兼容
mysql>FLUSH PRIVILEGES;
对于MySQL的主主架构,其实原理就是两台服务器Master1、Master2互为主从,双向复制
log-bin=/usr/local/mysql/data/mysql-bin #启用二进制日志(BBinary Log并指定其存储路径
binlog format=MIXED #定义二进制日志的记录格式为混合模式
server-id=1#为mysql实例分配一个唯一的服务器标识符
log-bin=/usr/local/mysql/data/mysql-bin #启用二进制日志(Biinary Log并指定其存储路径
binlog format=MIXED #定义二进制日志的记录格式为混合模式
server-id=2#为mysql实例分配一个唯一的服务器标识符
[root@localhost ~]# systemctl restart mysqld
[root@localhost ^]#mysql -u root -p
mysql> CREATE USER 'myslave' @'192.168.10.%' IDENTIFIED BY '123456';
Query OK, O rows affected (0.01 sec)
mysql> GRANT REPLICATION SLAVE ON *.* TO myslave' @' 192.168.10. %;
Query OK, O rows affected (0.01 sec)
mysql>ALTER USER 'myslave' @'192.168.10. %' IDENTIFIED WITH mysql_native_password BY '123456';
#MySQL 8.0默认使用caching_sha2_password 认证插件,将mysql_native_password替换为旧版认证插件,确保从库能兼容mysql>FLUSH PRIVILEGES;
mysql>show master status;其中File列显示日志名,Position列显示偏移量,这两个值在后面配置从服务器的时候需要。Slave应从该点上进行新的更新。
Master l
按主服务器结果更改下面命令中master_log_file和master_log_pos 参数
[root@localhost ^]# mysql -uroot -p
mysql>change master master_host=' 192.168. 10. 102' , master_user='myslave' ,
master_password=' 123456' master_log_file='mysql-bin. 0000001',master_1o
g_pos=157;
Query OK, O rows affected, 8 warnings (0.01 sec)启动同步。
mysql>start slave;
Query OK, O rows affected (0.00 sec)
查看Slave状态,确保以下两个值为YES
[root@localhost ^]# mysql -uroot -p -e "show slave staatus\G" | grep Yest
Enter password:
Slave IO Running: Yes
Slave SQL_Running: YesMaster2
按主服务器结果更改下面命令中master_log_file和master_log_pos 参数
[root@localhost ^]# mysql -uroot -p
mysql>change master master_host=' 192.168. 10. 101' , master_user='myslave' ,
master_password=' 123456' master_log_file='mysql-bin. 0000001',master_1o
g_pos=157;
Query OK, O rows affected, 8 warnings (0.01 sec)启动同步。
mysql>start slave;
Query OK, O rows affected (0.00 sec)
查看Slave状态,确保以下两个值为YES
[root@localhost ^]# mysql -uroot -p -e "show slave staatus\G" | grep Yest
Enter password:
Slave IO Running: Yes
Slave SQL_Running: Yes
该阶段操作在Keepalivedl、Keepalived2都要执行
[root@localhost~]# sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config
[root@localhost~]# setenforce 0
[root@localhost^]# systemctl disable firewalld
[root@localhost`]# systemctl stop firewalld
[root@localhost~]# dnf install haproxy
内容如下更改部分红色标注(Keepalivedl,Keepalived2配置相同
[root@localhost `]# vim /etc/haproxy/haproxy.cfgdefaults
mode tcp
log global
option teplog以下需要自行写入在配置文件末尾
listen mysql
bind 0.0.0.0;3306 #显式指定监听地址和端口
balance leastconn #负载均衡算法
server mysqll 192.168.10.101:3306 check port 3306maxconn 300
server mysql2 192.168.10.102:3306 check port 3306 maxconn 300注释:
>mode tcp:表示tcp代理
>listenmysql0.0.0.0.0:3306表示创建一个名为 mysql 的监听服务
>bind0.0.0.0:3306绑定到所有网卡的3306端口(MySQL默认端口),作为流量入口。
>balanceleastconn指定使用 最少连接数算法 分配请求,将新连接导向当前活跃连接最少的后端服务器,避免单点过载
>Server声明两个MySQL服务器节点mysqll 和mysql2,分别指向 192.168.10.101:3306 和 192.168.102:3306。
>check port3306表示通过检查节点的 3306端口是否响应,判断其存活状态
>maxconn300限制每个后端节点的最大并发连接数为300,防止节点被压垮
[root@localhost ^]# haproxy -c -f /etc/haproxy/haproxycfg
[root@localhost ^]# systemctl restart haproxy
使用测试用户test,访问haproxy的代理端口登录mysql
[root@localhost~]# mysql -utest -p123456 -h192.168.10.103 -P3306如果没有MySQL需自行下载
[root@localhost~]#dnf -y install mysql
该阶段操作在Keepalivedl、Keepalived2都要执行
[root@localhost~]# sed -i 's/SELINUX=enforcing/SELINUX=disabled/"/etc/selinux/config
[root@localhost~]# setenforce 0
[root@localhost`]# systemctl disable firewalld
[root@localhost`]# systemctl stop firewalld
[root@localhost ^]# dnf install keepalived
Keeppalivedl配置,红色标注为两台不同之处,需要注意
[root@localhost~]#cp /etc/keepalived/keepalived.conf.sample /etc/keepalived/keepalived.conf
[root@localhost ^]# vim /etc/keepalived/keepalived.conf
! Configuration File for keepalived
global_defs {
router_id rl //在keepalived2上改成r2}
vrrp_script chk_haproxy {
script "/etc/keepalived/chk.sh"
interval 2}
vrrp_instance VI_1 {
state BACKUP
nopreempt
interface ens33 #该为自己的
virtual_router_id 51
priority 100 //在keepalived2上改成99
advert_int 1authentication {
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'}
启用nopreempt的作用:
节点A(优先级100,配置 nopreempt)故障→节点B成为Master。
节点A恢复→不触发抢占,节点B继续作为Master,VII不切换。
仅当节点B故障时,节点A才会重新成为Master。
添加监控脚本并启动keepalived
[root@localhost~]# vim /etc/keepalived/chk.sh
#!/bin/bash
if [ $(ps -C haproxy --no-header | wc -1) -eq 0 ]; ther
/etc/init.d/keepalived stop
fi
[root@localhost`]# chmod +x /etc/keepalived/chk.sh
[root@localhost^]# systemctl start keepalived此处两台主机均配置为BACKUP,因此哪台先运行keepalived,VIP就在哪台上。本案例刚开始VIP运行在keepalivedl上
在keepalivedl测试查看VIP(注意查看VIP只能用ip命令,ifconfig不显示VIP)
[root@localhost~]# ip ainet 192.168.10.100/32 scope global ens33
[root@localhost ^]# mysql -utest -p123456 -h192.168.10.100
关闭masterl后,因为masterl、master2通过haproxy负载均衡,masterl关闭后,haproxy检测其状态异常,会从负载中移除,不进行流量转发,依然可以通过vip访问mysql,实现mysql的高可用
[root@localhost~]# ping 192.168.10.101 #pingmasterl发现已离线
PING 192.168.10.101(192.168.101)56(84)字节的数据。
来自192.168.10.104 icmp_seq=1 目标主机不可达
[root@localhost ^]# mysql -utest -p123456 -h192.1068.10.100
关闭keepalivedl后,keepalived检测到主节点离线,VIP192.168.10.10.100
会漂移至keepalived2节点,mysql依然可以访问
[root@localhost ~]# ip a #vip 192.168.10.100漂移至 keepalived2inet 192.168. 10. 104/24 brd 192.168.10.255 scope globalnoprefixroute ens33
inet 192.168.10.100/32 scope global ens33[root@localhost ~]# mysql -utest -p123456 -h192.168. 100