MySQL高可用
什么是MySQL高可用
MySQL 高可用(High Availability)是指通过冗余设计,确保数据库服务在单节点故障、网络中断或硬件损坏等异常情况下,仍能持续对外提供服务,同时保证数据一致性。其核心目标是实现“零停机、零数据丢失” 的业务连续性。
方案组成
MySQL 主主复制 + Keepalived + HAProxy 的高可用方案由三部分组成:
- MySQL 主主复制:两台 MySQL 实例互为主从,双向同步数据,均支持读写操作提供几余和扩展能力。
- Keepalived:通过 VRRP 协议管理虚拟 IP(VIP),监控 MySQL 状态,故障时自动将 VIP 漂移至存活节点,确保服务地址不变。
- HAProxy:作为反向代理和负载均衡器,将流量分发至 MySQL 节点,支持健康检查、读写分离(可选)和故障节点自动剔除。
优势
- 高可用性:Keepalived 实现秒级故障切换,HAProxy健康检查确保流量仅路由到正常节点,避免单点故障。
- 读写扩展:主主架构支持双节点并发写入,提升写入性能;HAProxy可配置读写分离,利用备节点分担读压力。
- 灵活扩展:可横向扩展 HAProxy 或 MySQL 节点,支持动态调整负载均衡策略(如轮询、权重)。
运维友好基于开源工具,无厂商锁定,社区支持丰富,适合自建数据库集群。
MySQL高可用
两台MySQL(双主)两台haproxy以及keepalived 一台客户机
MySQL高可用是建立于双主之间的
用脚本刷MySQL(上一节有步骤 这里不再陈述)
关闭防火墙 关闭内核 最好4台都做一下
systemctl stop firewalld
setenforce 0
01修改my.cnf
[client]
socket=/usr/local/mysql/data/mysql.sock
[mysqld]
socket=/usr/local/mysql/data/mysql.sock
bind-address = 0.0.0.0 server-id=1 #id不能相同 02id是2
log-bin=/usr/local/mysql/data/mysql-bin
binlog-format=MIXED
log-slave-updates=1 #这四行####!!!####
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[mysqld_safe]
log-error=/usr/local/mysql/data/error.log
#pid-file=/var/run/mariadb/mariadb.pid
02修改/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 server-id=2
log-bin=/usr/local/mysql/data/mysql-bin
binlog-format=MIXED
log-slave-updates=1skip-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[mysqld_safe]
log-error=/usr/local/mysql/data/error.log
#pid-file=/var/run/mariadb/mariadb.pid
01、02登录MySQL并创建用户
[root@localhost ~]# mysql -uroot -ppwd123 #登录MySQLmysql> create user 'myslave'@'%' identified by 'pwd123'; #创建用户mysql> grant replication slave on *.* to 'myslave'@'%'; #给用户授权mysql> alter user 'myslave'@'%' identified with mysql_native_password by 'pwd123'; #认证模块mysql> flush privileges; #刷新策略mysql> show master status; #记住位置
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000001 | 1149 | | | |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
02跟01的操作是一样的只有后面的位置是不一样的
mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000001 | 1148 | | | |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
01连接02
mysql> change master to master_host='192.168.10.102',master_user='myslave',master_password='pwd123',master_log_file='mysql-bin.000001',master_log_pos=1148;
Query OK, 0 rows affected, 8 warnings (0.01 sec)
02连接01
mysql> change master to master_host='192.168.10.101',master_user='myslave',master_password='pwd123',master_log_file='mysql-bin.000001',master_log_pos=1149;
Query OK, 0 rows affected, 8 warnings (0.01 sec)
01、02开启同步
mysql> start slave;
查看连接01也可以通过这种方式查看
mysql> show slave status\G
*************************** 1. row ***************************Slave_IO_State: Waiting for source to send eventMaster_Host: 192.168.10.101Master_User: myslaveMaster_Port: 3306Connect_Retry: 60Master_Log_File: mysql-bin.000001Read_Master_Log_Pos: 1149Relay_Log_File: localhost-relay-bin.000002Relay_Log_Pos: 326Relay_Master_Log_File: mysql-bin.000001Slave_IO_Running: Yes #还是两个yes就是连接成功Slave_SQL_Running: YesReplicate_Do_DB: Replicate_Ignore_DB: Replicate_Do_Table: Replicate_Ignore_Table: Replicate_Wild_Do_Table: Replicate_Wild_Ignore_Table: Last_Errno: 0Last_Error: Skip_Counter: 0Exec_Master_Log_Pos: 1149Relay_Log_Space: 540Until_Condition: NoneUntil_Log_File: Until_Log_Pos: 0Master_SSL_Allowed: NoMaster_SSL_CA_File: Master_SSL_CA_Path: Master_SSL_Cert: Master_SSL_Cipher: Master_SSL_Key: Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: NoLast_IO_Errno: 0Last_IO_Error: Last_SQL_Errno: 0Last_SQL_Error: Replicate_Ignore_Server_Ids: Master_Server_Id: 1Master_UUID: ff3d1710-1f2f-11f0-b012-000c29147990Master_Info_File: mysql.slave_master_infoSQL_Delay: 0SQL_Remaining_Delay: NULLSlave_SQL_Running_State: Replica has read all relay log; waiting for more updatesMaster_Retry_Count: 86400Master_Bind: Last_IO_Error_Timestamp: Last_SQL_Error_Timestamp: Master_SSL_Crl: Master_SSL_Crlpath: Retrieved_Gtid_Set: Executed_Gtid_Set: Auto_Position: 0Replicate_Rewrite_DB: Channel_Name: Master_TLS_Version: Master_public_key_path: Get_master_public_key: 0Network_Namespace:
1 row in set, 1 warning (0.00 sec)
可以通过创建库来确认验证结果
mysql> create database aaa; #创建库
02查看库
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| aaa |
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+
5 rows in set (0.00 sec)
至此 双主配置完成
03、04安装haproxy以及keepalived
关闭防火墙以及内核
systemctl stop firewalld #防火墙setenforce 0 #内核
下载haproxy
dnf -y install haproxy
修改haproxy配置文件
03、04操作一样
vim /etc/haproxy/haproxy.cfg
defaultsmode tcp #更改tcplog globaloption tcplog #更改tcpoption dontlognullretries 3timeout http-request 5stimeout queue 1mtimeout connect 5stimeout client 1mtimeout server 1mtimeout http-keep-alive 5stimeout check 5smaxconn 3000
将frontend main模板(包括fronted)以后的全部删掉
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
启动haproxy
systemctl start haproxy
netstat -anpt |grep haproxy #查看有没有启动进程
下载keepalived
dnf -y install keepalived
将keepalived的模板复制出来并换后缀
cd /etc/keepalived/
cp keepalived.conf.sample keepalived.conf
03更改配置文件
vim keepalived.confnotification_email_from Alexandre.Cassen@firewall.locsmtp_server 192.168.200.1smtp_connect_timeout 30router_id LVS_01 #idvrrp_skip_check_adv_addr#vrrp_strict #注销掉vrrp_garp_interval 0vrrp_gna_interval 0vrrp_instance VI_1 {state BACKUP #更改nopreempt #不让他抢占interface ens33 #网卡标识virtual_router_id 51priority 100 #优先级不用改advert_int 1authentication {auth_type PASSauth_pass 1111}virtual_ipaddress {192.168.10.100 #Vip#192.168.200.17# 192.168.200.18}
后面不用的也删掉
04修改配置文件
notification_email_from Alexandre.Cassen@firewall.locsmtp_server 192.168.200.1smtp_connect_timeout 30router_id LVS_02 #idvrrp_skip_check_adv_addr#vrrp_strict #注销掉 严格模式vrrp_garp_interval 0vrrp_gna_interval 0vrrp_instance VI_1 {state BACKUP #设置成BACKUPinterface ens33 #网卡标签virtual_router_id 51priority 90 #优先级设置低一点advert_int 1authentication {auth_type PASSauth_pass 1111}virtual_ipaddress {192.168.10.100 #Vip#192.168.200.17# 192.168.200.18}后面都删掉
因为此配置没有检查haproxy是否工作正常 所以使用脚本来检测是否正常
vim chk.sh
#!/bin/bash
if [ $(ps -C haproxy --no-header | wc -l) -eq 0]
thensystemctl stop keepalived
fi
调用keepalived(03、04一样的操作)
vim keepalived.conf
调用脚本(在varrp_instance上面)
vrrp_script chk_haproxy { script "/etc/keepalived/chk.sh"interval 2
}track_script { #运行(在Vip外面写)chk_haproxy}
给执行权限
chmod +x chk.sh
验证:查看vip移动了没有
启动haproxy与keepalived
使用ip a 查看04的vip
[root@localhost keepalived]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00inet 127.0.0.1/8 scope host lovalid_lft forever preferred_lft foreverinet6 ::1/128 scope host noprefixroute valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000link/ether 00:0c:29:db:b4:66 brd ff:ff:ff:ff:ff:ffinet 192.168.10.104/24 brd 192.168.10.255 scope global noprefixroute ens33valid_lft forever preferred_lft foreverinet 192.168.10.100/32 scope global ens33 #这里!!!!!!!valid_lft forever preferred_lft foreverinet6 fe80::20c:29ff:fedb:b466/64 scope link noprefixroute valid_lft forever preferred_lft forever
03的vip
[root@localhost keepalived]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00inet 127.0.0.1/8 scope host lovalid_lft forever preferred_lft foreverinet6 ::1/128 scope host noprefixroute valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000link/ether 00:0c:29:db:b4:66 brd ff:ff:ff:ff:ff:ffinet 192.168.10.103/24 brd 192.168.10.255 scope global noprefixroute ens33valid_lft forever preferred_lft foreverinet6 fe80::20c:29ff:fedb:b466/64 scope link noprefixroute valid_lft forever preferred_lft forever
客户机使用haproxy代理访问MySQL(会卡顿 但再次查看就没有问题)
mysql -umyslave -ppwd123 -P3306 -h192.168.10.103MySQL [(none)]> show databases; #卡顿
ERROR 2013 (HY000): Lost connection to MySQL server during query
MySQL [(none)]> show databases; #再次查看是没有问题的
ERROR 2006 (HY000): MySQL server has gone away
No connection. Trying to reconnect...
Connection id: 18
Current database: *** NONE ***+--------------------+
| Database |
+--------------------+
| information_schema |
| performance_schema |
+--------------------+
2 rows in set (0.006 sec)MySQL [(none)]>