一、项目说明
1.1 业务需求
- 某企业由于业务增加,超出了单库性能1阈值,则需要构建高可用的数据库服务器集群,且在业务增长初期,读写业务各半,需选择Active-Active Cluster集群架构,为了保证活性,使用恰当的技术实现high availability,要求架构图如下:

- 为了实现自动化运维,预使用开源监控实时报警软件实现服务器的检测、大屏展示,要求使用独立主机安装软件检测数据库集群的性能,以仪表盘形式展示
- 具体要求
- 网络配置:确保集群中的MySQL服务器之间的网络连接稳定可靠,避免网络延迟或丢包对集群性能造成影响。
- 同步参数配置:对于需要数据同步的集群方案(如主从复制和组复制),需要合理配置同步参数,确保数据的实时性和一致性。
- 备份和恢复策略:制定完善的备份和恢复策略,定期备份集群数据,并测试恢复流程的可行性,以确保在发生故障时能够快速恢复数据和服务。
- 监控和告警:使用监控工具对集群进行实时监控,并设置合理的告警阈值。当集群出现异常情况时,能够及时发现并处理。
1.2 项目设计思路
-
MYSQL集群高可用使用双主双活+keepalived实现
-
MYSQL数据监控平台使用mysqld_exporter+prometheus+Grafana三件套实现
-
集群及监控平台搭建完毕后可以实现企业内部的mysql数据库双主机在线增加高可用性,通过keepalived的故障检测和VIP漂移能力使得发生故障后使用者无感知,增加系统的容错能力,通过监控平台实现mysql数据库监控可视化
1.3 项目特点
- 综合项目从主从复制原理、数据同步方式、主从架构模式、主从架构/双主架构、高可用、数据可视化一步步从零搭建出一个完善的数据库集群/监控平台
- 综合项目完成后可以实现对MYSQL数据库高级运维知识的巩固,通过参与实际项目增加工作实战经验,提升技术能力、故障判断检测维护能力、充实简历项目经历
- 通过prometheus数据库监控三件套的项目搭建,可以掌握数据监控的知识应用能力,通过监控大屏数据的展示使得数据可视化得以实现,使得运维更自动化、直观化
- 该项目进一步巩固和掌握云原生高级数据
- 库部分的知识以及数据监控可视化的知识点
二、项目环境
2.1 项目拓扑结构

2.2 软硬件环境清单
|---------|-----------------------------------|-------------------------------|----------------------------------------------------------------------------------------------------|
| 主机名 | IP地址 | 硬件 | 软件 |
| master1 | 192.168.56.142 VIP:192.168.56.200 | cpu:1颗2核 内存:8G HDD:32G 网络:NAT | VmWare17.6.3 OpenEuler22.03 SP4 mysql8.0.37 keepalived-2.2.4 |
| master2 | 192.168.56.143 VIP:192.168.56.200 | cpu:1颗2核 内存:8G HDD:32G 网络:NAT | VmWare17.6.3 OpenEuler22.03 SP4 mysql8.0.37 keepalived-2.2.4 |
| monitor | 192.168.56.144 | cpu:1颗2核 内存:8G HDD:32G 网络:NAT | VmWare17.6.3 OpenEuler22.03 SP4 mysqld_exporter-0.15.1 prometheus-2.53.2 grafana-enterprise-11.1.2 |
三、项目实现步骤分析
3.1 系统平台部署
1、部署三台OpenEuler22.03操作系统的虚拟主机
2、进行系统初始化配置:
- 配置主机名
- 关闭防火墙
- 关闭selinux
- 配置IP地址等
- 配置hosts映射文件
3.2 mysql安装
1、通用二进制包安装mysql
2、配置mysql系统服务
3.3 部署高可用mysql双主集群
1、配置账户
2、配置主主复制
3、安装keepalived并配置
3.4 安装配置监控平台
1、安装Mysqld_Exporter+Prometheus+grafana-enterprise
2、配置监控平台组件
3.5 压力测试
四、项目实现过程
4.1 OpenEuler系统部署
4.1.1 创建虚拟机示例
选择linux操作系统,选择其他linux5.x内核64位版本

选择自定义硬件,移除声卡和USB接口,设置连接选择ISO镜像文件,显示关闭加速3D图形

其余配置自行完成,然后创建虚拟机实例完毕
4.1.2 OpenEuler22.03操作系统安装部署
进入后选择安装目的地进行分区,选择自定义,选择完成,然后自定义分区,/boot:1g,swap:4g,/:剩余

其余配置自行完成后开始安装操作系统
4.1.3 环境配置
1、修改主机名2、
bash
[root@localhost ~]# hostnamectl set-hostname master1
bash
[root@localhost ~]# hostnamectl set-hostname master2
bash
[root@localhost ~]# hostnamectl set-hostname monitor
2、配置网络
bash
# master1的ip为192.168.56.142 master2的ip为192.168.56.143 monitor的ip为192.168.56.144
nmcli c modify ipv4.method manual ipv4.address 192.168.56.142 ipv4.gateway 192.168.56.2 ipv4.dns 114.114.114.114
nmcli c reload # 重载
nmcli c up ens32 # 激活网卡
3、关闭三台主机防火墙及selinux
bash
# 关闭selinux
sed 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config
# 关闭防火墙并且取消开机自启动
systemctl stop firewalld
systemctl disable firewalld
# 重启生效
reboot
# 重启后使用以下两个命令确认selinux和防火墙成功关闭
getenforce # 应输出disabled
systemctl status firewalld # 防火墙状态应为dead
4、安装和更新软件
bash
dnf install vim make gcc tree net-tools tar -y
dnf update -y
4.2 mysql安装部署
以master1为例(master1与master2操作一致)
4.2.1 官网下载mysql通用二进制安装包

4.2.2 解压缩
bash
[root@master1 ~]# ls
anaconda-ks.cfg mysql-8.0.37-linux-glibc2.17-x86_64.tar.xz
[root@master1 ~]# tar xvf mysql-8.0.37-linux-glibc2.17-x86_64.tar.xz
4.2.3 准备工作
bash
# 将解压出来的目录移动到linux的默认安装目录
[root@master1 ~]# mv mysql-8.0.37-linux-glibc2.17-x86_64 /usr/local/mysql
# 创建mysql的用户组和系统用户
[root@master1 ~]# cd /usr/local/mysql/
[root@master1 mysql]# groupadd mysql
[root@master1 mysql]# useradd -r -g mysql -s /bin/false mysql
# 创建存储mysql数据文件的目录
[root@master1 mysql]# mkdir data
# 设置mysql目录的账户及工作组,生产环境中不要使用root
[root@master1 mysql]# chown -R mysql:mysql /usr/local/mysql/
4.2.4 初始化软件
bash
[root@master1 mysql]# bin/mysqld --initialize --user=mysql --basedir=/usr/local/mysql --datadir=/usr/local/mysql/data # 注意:需要复制密码
[root@master1 mysql]# bin/mysqld_safe --user=mysql & # 使用后台方式以mysql用户身份启动 MySQL 服务器,mysqld_safe 是一个用于启动和监控 MySQL 服务器的脚本
# 注意:此时上述命令执行完毕处于后台运行状态,需要另行启动一个终端
[root@master1 ~]# ps -ef | grep mysql # 查看进程运行状态
[root@master1 ~]# cd /usr/local/mysql
[root@master1 ~]# bin/mysql -uroot -p # 登录,可能报错
# 报错,需要找到下面的文件进行软连接
[root@master1 ~]# ln -s /usr/lib64/libncurses.so.6.3 /usr/lib64/libncurses.so.5
[root@master1 ~]# ln -s /usr/lib64/libtinfo.so.6.3 /usr/lib64/libtinfo.so.5
[root@master1 ~]# bin/mysql -u root -p
Enter password: # 粘贴之前的初始密码
mysql> alter user 'root'@'localhost' identified with caching_sha2_password by '123456'; 修改密码
mysql> flush privileges; # 刷新
mysql> use mysql; # 查看账户信息
mysql> select user, host, plugin from mysql.user;
+------------------+-----------+-----------------------+
| user | host | plugin |
+------------------+-----------+-----------------------+
| mysql.infoschema | localhost | caching_sha2_password |
| mysql.session | localhost | caching_sha2_password |
| mysql.sys | localhost | caching_sha2_password |
| root | localhost | mysql_native_password |
+------------------+-----------+-----------------------+
4 rows in set (0.00 sec)
mysql>exit
[root@master1 ~]# ps -ef | grep mysql
[root@master1 ~]# kill -9 pid号 # 在当前终端关闭运行的mysql
注意:以上准备工作和初始化工作是根据mysql官方文档给出的配置教程加上微调而成,有疑问或者异议可自行访问官方mysql8.0通用二进制包安装文档,传送门:MySQL :: MySQL 8.0 Reference Manual :: 2.2 Installing MySQL on Unix/Linux Using Generic Binaries

4.2.4 编辑mysql配置文件
bash
# 新建配置文件
[root@masterA mysql]# vim /etc/my.cnf
[client]
port = 3306
socket = /tmp/mysql.sock
[mysqld]
port = 3306
basedir = /usr/local/mysql
datadir = /usr/local/mysql/data
tmpdir = /tmp
socket = /tmp/mysql.sock
character-set-server = utf8mb4
collation-server = utf8mb4_general_ci
default-storage-engine=INNODB
log_error = error.log
4.2.5 配置启动脚本
bash
[root@master1 ~]# cd /usr/local/mysql/support-files
[root@master1 support-files]# cp -a mysql.server /etc/init.d/mysql
[root@master1 support-files]# vim /etc/init.d/mysql # 增加=之后的内容
basedir=/usr/local/mysql
datadir=/usr/local/mysql/data
[root@master1 init.d]# cd ~
[root@master1 ~]# vim ~/.bash_profile # 设置环境变量需添加如下语句
export PATH=$PATH:/usr/local/mysql/bin
[root@master1 ~]# source ~/.bash_profile
[root@master1 ~]# systemctl daemon-reload # 重载系统配置
[root@master1 ~]# systemctl start mysql
[root@master1 ~]# /usr/lib/systemd/systemd-sysv-install enable mysql # 开机启动
[root@master1 ~]# mysql -uroot -p
mysql> update mysql.user set host="%" where user="root";
mysql> flush privileges;
该工作做完后mysql即可实现开机自启动
4.3 mysql集群搭建
-
搭建主-主集群,两个节点都是主库,也都属于对方的从库,也就是两者之间会相互同步数据,这时为了防止主键出现冲突,一般都会通过设置数据库自增步长的方式来防重
-
主-主架构集群适用于中读写请求的比例对半开,同时整体的并发量也不算低,至少超出了单库的承载阈值的场景下,架构图如下:

4.3.1 master1节点配置
1、修改配置文件
bash
[root@master1 ~]# systemctl stop mysql
[root@master1 ~]# vim /etc/my.cnf
[client]
port = 3306
socket = /tmp/mysql.sock
[mysqld]
port = 3306
basedir = /usr/local/mysql
datadir = /usr/local/mysql/data
tmpdir = /tmp
socket = /tmp/mysql.sock
character-set-server = utf8mb4
collation-server = utf8mb4_general_ci
default-storage-engine=INNODB
log_error = error.log
# ------主节点配置-------
# 当前节点在集群中的唯一标识
server-id=1
# 开启bin-log日志,并为bin-log日志取个前缀名(有默认值可不写)
log-bin=mysql-bin-log
# 同步复制时过滤的库(主要将一些不需要备份/同步库写进来)
# 也可以通过binlog-do-db=xx1,xx2... 来指定要复制的目标库
binlog-ignore-db=mysql
# 指定bin-log日志的格式为混合模式(默认为statement)
binlog_format=mixed
# 设置单个binlog日志文件的最大容量
max_binlog_size=1024M
# ------从节点配置-------
# 开启relay-log日志(同样可以指定前缀名)
relay_log=mysql-relay-log
# 开启存储过程、函数、触发器等内容的同步功能
log_bin_trust_function_creators=true
# 同步执行跳过一些错误码(防止同步写入时出现错误导致复制中断)
slave_skip_errors=1062
# ------自增序列配置-------
# 设置自增初始值为1
auto_increment_offset=1
# 设置自增步长为2,自增序列为{1、3、5、7、9.....}
auto_increment_increment=2
-
注意
-
server-id=1,为集群中本机标识,必须唯一
-
由于master1即使主节点又是从节点,则必须设置从节点配置
-
为了保证2个节点数据的一致性,需要开启自增序列配置,master1节点跳步为1 3 5 7 9...
-
2、创建用于数据同步的账户
sql
[root@master1 ~]# systemctl start mysql
mysql> create user 'mback'@'%' identified with caching_sha2_password by '123456';
mysql> grant replication slave on *.* to 'mback'@'%';mysql> create user 'mback'@'%' identified with caching_sha2_password by '123456';
Query OK, 0 rows affected (0.01 sec)
mysql> grant replication slave on *.* to 'mback'@'%';
Query OK, 0 rows affected (0.01 sec)
4.3.2 master2节点配置
1、修改配置文件
bash
[root@master2 ~]# systemctl stop mysql
[root@master2 ~]# vim /etc/my.cnf
[client]
port = 3306
socket = /tmp/mysql.sock
[mysqld]
port = 3306
basedir = /usr/local/mysql
datadir = /usr/local/mysql/data
tmpdir = /tmp
socket = /tmp/mysql.sock
character-set-server = utf8mb4
collation-server = utf8mb4_general_ci
default-storage-engine=INNODB
log_error = error.log
# ------主节点配置-------
# 当前节点在集群中的唯一标识
server-id=2
# 开启bin-log日志,并为bin-log日志取个前缀名(有默认值可不写)
log-bin=mysql-bin-log
# 同步复制时过滤的库(主要将一些不需要备份/同步库写进来)
# 也可以通过binlog-do-db=xx1,xx2... 来指定要复制的目标库
binlog-ignore-db=mysql
# 指定bin-log日志的格式为混合模式(默认为statement)
binlog_format=mixed
# 设置单个binlog日志文件的最大容量
max_binlog_size=1024M
# ------从节点配置-------
# 开启relay-log日志(同样可以指定前缀名)
relay_log=mysql-relay-log
# 开启存储过程、函数、触发器等内容的同步功能
log_bin_trust_function_creators=true
# 同步执行跳过一些错误码(防止同步写入时出现错误导致复制中断)
slave_skip_errors=1062
# ------自增序列配置-------
# 设置自增初始值为2
auto_increment_offset=2
# 设置自增步长为2,自增序列为{1、3、5、7、9.....}
auto_increment_increment=2
-
注意:
-
master2节点的server-id=2,不能和master1的server-id相同
-
设置自增初始值为2,则master2节点跳步为2 4 6 8 ...
-
2、创建用于数据同步的账户
sql
mysql> create user 'mback'@'%' identified with caching_sha2_password by '123456';
Query OK, 0 rows affected (0.01 sec)
mysql> grant replication slave on *.* to 'mback'@'%';
Query OK, 0 rows affected (0.01 sec)
4.3.3 建立master1节点主从关系
-
由于建立的是主-主架构集群,相互为对方的从节点,则两个节点都通过
root账号登录 -
此时master1为从节点,master2为主节点
-
先在master2上查看同步的日志名称及同步点号
sql
# 在master2上执行
mysql> show master status;
+----------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+----------------------+----------+--------------+------------------+-------------------+
| mysql-bin-log.000002 | 694 | | mysql | |
+----------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
# 日志文件:mysql-bin-log.000002
# 日志数据点:694
- master1 节点上建立复制关系:
sql
mysql> change master to
-> master_host='192.168.56.143',master_user='mback',master_password='123456',master_port=3306,
-> master_log_file='mysql-bin-log.000002',master_log_pos=694,get_master_public_key=1;
Query OK, 0 rows affected, 9 warnings (0.01 sec)
mysql> start slave;
Query OK, 0 rows affected, 1 warning (0.00 sec)
mysql> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for source to send event
Master_Host: 192.168.56.143
Master_User: mback
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin-log.000010
Read_Master_Log_Pos: 157
Relay_Log_File: mysql-relay-log.000031
Relay_Log_Pos: 381
Relay_Master_Log_File: mysql-bin-log.000010
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Replicate_Do_DB:
Replicate_Ignore_DB:
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno: 0
Last_Error:
Skip_Counter: 0
Exec_Master_Log_Pos: 157
Relay_Log_Space: 764
Until_Condition: None
Until_Log_File:
Until_Log_Pos: 0
Master_SSL_Allowed: No
Master_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: No
Last_IO_Errno: 0
Last_IO_Error:
Last_SQL_Errno: 0
Last_SQL_Error:
Replicate_Ignore_Server_Ids:
Master_Server_Id: 2
Master_UUID: ef4971b4-c4fb-11f0-8360-000c2940b74e
Master_Info_File: mysql.slave_master_info
SQL_Delay: 0
SQL_Remaining_Delay: NULL
Slave_SQL_Running_State: Replica has read all relay log; waiting for more updates
Master_Retry_Count: 86400
Master_Bind:
Last_IO_Error_Timestamp:
Last_SQL_Error_Timestamp:
Master_SSL_Crl:
Master_SSL_Crlpath:
Retrieved_Gtid_Set:
Executed_Gtid_Set:
Auto_Position: 0
Replicate_Rewrite_DB:
Channel_Name:
Master_TLS_Version:
Master_public_key_path:
Get_master_public_key: 1
Network_Namespace:
1 row in set, 1 warning (0.00 sec)

4.3.4 建立master2节点主从关系
-
此时master2为从节点,master1为主节点
-
先在master1上查看同步的日志名称及同步点号
sql
# 在master1上执行
mysql> show master status;
+----------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+----------------------+----------+--------------+------------------+-------------------+
| mysql-bin-log.000001 | 695 | | mysql | |
+----------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
# 日志文件:mysql-bin-log.000001
# 日志数据点:695
- master2节点上建立复制关系:
sql
mysql> change master to master_host='192.168.56.142',master_user='mback',master_password='123456',master_port=3306,
-> master_log_file='mysql-bin-log.000001',master_log_pos=695,get_master_public_key=1;
Query OK, 0 rows affected, 9 warnings (0.01 sec)
mysql> start slave;
Query OK, 0 rows affected, 1 warning (0.01 sec)
4.3.5 局部测试
测试主主架构是否能互相同步数据
1、master1执行,master2查看
- master1建立数据库
sql
mysql> create database test1;
Query OK, 1 row affected (0.01 sec)
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
| test1 |
+--------------------+
5 rows in set (0.00 sec)
- master2查看
sql
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
| test1 |
+--------------------+
5 rows in set (0.01 sec)
- 此时master1(主)----master2(从)构建完毕
2、master2执行,master1查看
- master2中执行创建表
sql
mysql> use test1;
mysql> create table back_test (`user_id`int(8) not null,`user_name` varchar(255) not null,`user_sex` varchar(255) not null,`passwordd` varchar(255) not null,`register_time` datetime);
Query OK, 0 rows affected, 1 warning (0.01 sec)
mysql> desc back_test;
+---------------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------------+--------------+------+-----+---------+-------+
| user_id | int | NO | | NULL | |
| user_name | varchar(255) | NO | | NULL | |
| user_sex | varchar(255) | NO | | NULL | |
| password | varchar(255) | NO | | NULL | |
| register_time | datetime | YES | | NULL | |
+---------------+--------------+------+-----+---------+-------+
5 rows in set (0.00 sec)
mysql> exit
- master1查看是否同步数据
sql
mysql> use test1;
mysql> desc back_test;
+---------------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------------+--------------+------+-----+---------+-------+
| user_id | int | NO | | NULL | |
| user_name | varchar(255) | NO | | NULL | |
| user_sex | varchar(255) | NO | | NULL | |
| password | varchar(255) | NO | | NULL | |
| register_time | datetime | YES | | NULL | |
+---------------+--------------+------+-----+---------+-------+
5 rows in set (0.00 sec)
mysql> exit
- 至此master1(从)----master2(主)构建完毕
4.4 keepalived故障转移的高可用环境配置
4.4.1 说明
-
Keepalived即保持存活,是一种轻量化的高可用方案,用来防止单点故障
-
Keepalived的工作原理是VRRP(Virtual Router Redundancy Protocol)虚拟路由冗余协议。
-
Keepalived通过VIP虚拟IP的漂移实现高可用,在相同集群内发送组播包,master1和master2主通过VRRP协议发送组播包,告诉从主的状态。
-
Keepalived会虚拟出一个VIP地址代理2台服务器向外界提供服务
-
当Keepalived实际代理master1时,若master1出现故障,keepalived通过自身机制,自动将master2作为实际代理主服务器,不需要人工干预去修改mysql配置信息,从而实现了高可用

4.4.2 步骤
-
2台MySql服务器安装keepalived软件包
-
配置服务
-
模拟故障进行测试
4.4.3 master1节点配置
- 安装keepalived
bash
[root@master1 ~]# yum install keepalived -y
- master1节点配置keepalived
bash
[root@masterA ~]# vim /etc/keepalived/keepalived.conf
! Configuration File for keepalived
global_defs {
router_id mysql-master01 # keepalived服务器的一个标识,每台机子不同
}
vrrp_instance VI_1 {
state BACKUP # 指定keepalived的角色, BACKUP模式将根据优先级决定主或从
interface ens32 # 监测的网卡名
virtual_router_id 51 # 虚拟路由标识,确保和master2相同
priority 100 # 用来选举master的数值
nopreempt
advert_int 1
authentication { # 认证区域
auth_type PASS
auth_pass 1111
}
virtual_ipaddress { # 指定VIP地址
192.168.56.200
}
}
# 虚拟服务器,需要指定虚拟IP地址和服务端口,IP与端口之间用空格隔开
virtual_server 192.168.56.200 3306 {
delay_loop 6 # 设置运行情况检查时间,单位是秒
lb_algo rr # 设置后端调度算法
lb_kind DR # 设置LVS实现负载均衡的机制
persistence_timeout 50 # 会话保持时间,单位是秒
protocol TCP # 指定转发协议类型
real_server 192.168.56.142 3306 { # 真实服务器IP地址及端口
notify_down /etc/keepalived/chk_mysql.sh
weight 1 # 配置服务节点的权值
TCP_CHECK {
connect_port 3306 # 健康检查端口
connect_timeout 3 # 连接超时时间
retry 3 # 重连次数
delay_before_retry 3 # 重连间隔时间
}
}
}
- 配置mysql健康检查脚本
bash
[root@master1 ~]# vim /etc/keepalived/chk_mysql.sh
#!/bin/bash
counter=$(netstat -na|grep "LISTEN"|grep "3306"|wc -l)
if [ "${counter}" -eq 0 ]; then
killall keepalived
fi
# 通过端口记录数判断mysql是否运行,mysql停止后终止keepalived,当然也可以在抢救一下
[root@masterA ~]# chmod +x /etc/keepalived/chk_mysql.sh
[root@masterA ~]# systemctl start keepalived
[root@masterA ~]# systemctl status keepalived
[root@masterA ~]# ip a

4.4.4 master2节点配置
- 安装keepalived
bash
[root@master2 ~]# yum install keepalived -y
- masterB节点配置keepalived
bash
[root@masterB ~]# vim /etc/keepalived/keepalived.conf
! Configuration File for keepalived
global_defs {
router_id mysql-master02 # 注意与master1区分开来
}
vrrp_instance VI_1 {
state BACKUP
interface ens32 # 注意网卡接口名
virtual_router_id 51
priority 50 # 注意选举参数
nopreempt
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.56.200
}
}
virtual_server 192.168.56.200 3306 {
delay_loop 6
lb_algo rr
lb_kind DR
persistence_timeout 50
protocol TCP
real_server 192.168.56.143 3306 { # master2地址及端口
notify_down /etc/keepalived/chk_mysql.sh
weight 1
TCP_CHECK {
connect_port 3306
connect_timeout 3
retry 3
delay_before_retry 3
}
}
}
bash
[root@masterB ~]# vim /etc/keepalived/chk_mysql.sh
#!/bin/bash
counter=$(netstat -na|grep "LISTEN"|grep "3306"|wc -l)
if [ "${counter}" -eq 0 ]; then
killall keepalived
fi
bash
[root@masterB ~]# chmod +x /etc/keepalived/chk_mysql.sh
[root@masterB ~]# systemctl start keepalived
[root@masterB ~]# systemctl status keepalived
4.4.5 局部测试
-
原理:当master1服务器宕机后,VIP会自动漂移至master2服务器并继续向外提供mysql服务
-
步骤:
-
在master1中停用mysql
-
查看VIP是否漂移
-
故障修复
-
-
master1中执行
bash
[root@master1 ~]# systemctl status mysql # 查看mysql状态
● mysql.service - LSB: start and stop MySQL
Loaded: loaded (/etc/rc.d/init.d/mysql; generated)
Active: active (running) since Wed 2025-11-19 15:14:54 CST; 25min ago
[root@master1 ~]# systemctl status keepalived
● keepalived.service - LVS and VRRP High Availability Monitor
Loaded: loaded (/usr/lib/systemd/system/keepalived.service; disabled; vendor preset: disabled)
Active: active (running) since Wed 2025-11-19 15:29:19 CST; 11min ago
[root@master1 ~]# 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
valid_lft forever preferred_lft forever
2: ens32: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
link/ether 00:0c:29:82:a4:47 brd ff:ff:ff:ff:ff:ff
inet 192.168.56.142/24 brd 192.168.56.255 scope global dynamic noprefixroute ens32
valid_lft 1117sec preferred_lft 1117sec
inet 192.168.56.200/32 scope global ens32 # 此时VIP正在监听
valid_lft forever preferred_lft forever
inet6 fe80::20c:29ff:fe82:a447/64 scope link noprefixroute
valid_lft forever preferred_lft forever
[root@master1 ~]# systemctl stop mysql # 模拟宕机
[root@master1 ~]# ip a # VIP消失
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
valid_lft forever preferred_lft forever
2: ens32: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
link/ether 00:0c:29:82:a4:47 brd ff:ff:ff:ff:ff:ff
inet 192.168.56.142/24 brd 192.168.56.255 scope global dynamic noprefixroute ens32
valid_lft 1082sec preferred_lft 1082sec
inet6 fe80::20c:29ff:fe82:a447/64 scope link noprefixroute
valid_lft forever preferred_lft forever
[root@master1 ~]# systemctl status keepalived # 已停用
○ keepalived.service - LVS and VRRP High Availability Monitor
Loaded: loaded (/usr/lib/systemd/system/keepalived.service; disabled; vendor preset: disabled)
Active: inactive (dead)
- master2执行
bash
[root@master2 ~]# 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
valid_lft forever preferred_lft forever
2: ens32: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
link/ether 00:0c:29:40:b7:4e brd ff:ff:ff:ff:ff:ff
inet 192.168.56.143/24 brd 192.168.56.255 scope global dynamic noprefixroute ens32
valid_lft 1006sec preferred_lft 1006sec
inet 192.168.56.200/32 scope global ens32 # VIP已漂移,继续服务
valid_lft forever preferred_lft forever
inet6 fe80::20c:29ff:fe40:b74e/64 scope link noprefixroute
valid_lft forever preferred_lft forever
- master1中恢复msyql服务和keepalived服务,注意必须先恢复msyql服务
bash
[root@master1 ~]#
[root@master1 ~]# systemctl start mysql
[root@master1 ~]# systemctl start keepalived
[root@master1 ~]# up a
-bash: up:未找到命令
[root@masterA ~]# 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
valid_lft forever preferred_lft forever
2: ens32: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
link/ether 00:0c:29:82:a4:47 brd ff:ff:ff:ff:ff:ff
inet 192.168.56.142/24 brd 192.168.56.255 scope global dynamic noprefixroute ens32
valid_lft 1039sec preferred_lft 1039sec
inet6 fe80::20c:29ff:fe82:a447/64 scope link noprefixroute
valid_lft forever preferred_lft forever
# 即使master1恢复后,VIP也不会被抢占
4.5 安装监控平台
4.5.1 说明
- 涉及的软件及端口
|-----------------|------|
| 服务 | 端口 |
| Prometheus | 9090 |
| Mysqld_exporter | 9194 |
| Grafana | 3000 |
4.5.2 部署Mysqld_exporter
- Mysql_exporter是用来收集MysQL数据库相关指标且需要连接到数据库并有相关权限。
- 下载安装包并解压缩:https://prometheus.io/download/
bash
# 监控主机操作
[root@monitor ~]# ls
anaconda-ks.cfg mysqld_exporter-0.15.1.linux-amd64.tar.gz
[root@monitor ~]# tar xvf mysqld_exporter-0.15.1.linux-amd64.tar.gz
mysqld_exporter-0.15.1.linux-amd64/
mysqld_exporter-0.15.1.linux-amd64/LICENSE
mysqld_exporter-0.15.1.linux-amd64/mysqld_exporter
mysqld_exporter-0.15.1.linux-amd64/NOTICE
[root@monitor ~]# mv mysqld_exporter-0.15.1.linux-amd64 /usr/local/mysqld_exporter
[root@monitor ~]# cd /usr/local/mysqld_exporter/
[root@monitor mysqld_exporter]# ls
LICENSE mysqld_exporter NOTICE
- 常见配置文件
bash
[root@monitor mysqld_exporter]# vim .my.cnf # 注意为隐藏文件
[client]
user = exporter # 该账户需要再2台mysql节点新建
password = 123456 # 登录密码
host = 192.168.56.200 # 使用VIP访问
port = 3306
- 两台mysql节点创建exporter用户并授权
sql
# master1操作
mysql> create user 'exporter'@'%' identified with caching_sha2_password by '123456';
Query OK, 0 rows affected (0.01 sec)
mysql> grant process,replication client,select on *.* to 'exporter'@'%';
Query OK, 0 rows affected (0.00 sec)
mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)
sql
# master2操作,由于设置了主-主集群架构,master1创建账户后会同步到master2,只需查看即可
[root@master2 ~]# mysql -uroot -p
Enter password:
mysql> select user ,host from mysql.user;
+------------------+-----------+
| user | host |
+------------------+-----------+
| exporter | % | # 已经同步
| mback | % |
| mysql.infoschema | localhost |
| mysql.session | localhost |
| mysql.sys | localhost |
| root | localhost |
+------------------+-----------+
6 rows in set (0.00 sec)
mysql> exit
- 配置mysqld_exporter的系统服务
bash
# monitor节点操作
[root@monitor ~]# vim /usr/lib/systemd/system/mysqld_exporter.service
[Unit]
Description=https://prometheus.io
[Service]
Restart=on-failure
ExecStart=/usr/local/mysqld_exporter/mysqld_exporter --config.my-cnf=/usr/local/mysqld_exporter/.my.cnf --web.listen-address=:9104
[Install]
WantedBy=multi-user.target
- 刷新服务配置并启动服务
bash
[root@monitor mysqld_exporter]# systemctl daemon-reload
[root@monitor mysqld_exporter]# systemctl enable --now mysqld_exporter.service
Created symlink /etc/systemd/system/multi-user.target.wants/mysqld_exporter.service → /usr/lib/systemd/system/mysqld_exporter.service.
[root@monitor mysqld_exporter]# systemctl status mysqld_exporter.service
- 通过浏览器输入http://192.168.56.144:9104/metrics,查看监控抓取msyql服务器的数据

4.5.3 部署Prometheus
-
Prometheus是一个开源系统监控和警报工具包,最初由SoundCloud构建。自2012年成立以来,许多公司和组织都采用了Prometheus,该项目拥有非常活跃的开发人员和用户社区。它现在是一个独立的开源项目,独立于任何公司维护。
-
Prometheus于2016年加入了云原生计算基金会,成为继Kubernetes之后的第二个托管项目。
-
架构图:

- 下载安装包并解压缩:https://prometheus.io/download/ ,选择2.53.2 LTS版本
bash
# monitor操作
[root@monitor ~]# tar xvf prometheus-2.53.2.linux-amd64.tar.gz
[root@monitor ~]# mv prometheus-2.53.2.linux-amd64 /usr/local/prometheus
[root@monitor ~]# cd /usr/local/prometheus
[root@monitor prometheus]# ls
console_libraries consoles LICENSE NOTICE prometheus prometheus.yml promtool
[root@monitor prometheus]# cd ~
- 新建prometheus账户
bash
[root@monitor ~]# useradd --no-create-home --shell /bin/false prometheus
[root@monitor ~]# chown -R prometheus:prometheus /usr/local/prometheus
- 配置Prometheus系统服务
bash
# monitor操作
[root@monitor ~]# vim /usr/lib/systemd/system/prometheus.service
[Unit]
Description=Prometheus
Wants=network-online.target
After=network-online.target
[Service]
User=prometheus
Group=prometheus
Type=simple
ExecStart=/usr/local/prometheus/prometheus --config.file /usr/local/prometheus/prometheus.yml --storage.tsdb.path /usr/local/prometheus/data
[Install]
WantedBy=multi-user.target
- 刷新服务配置并启动服务
bash
[root@monitor ~]# systemctl daemon-reload
[root@monitor ~]# systemctl enable --now prometheus
[root@monitor ~]# systemctl status prometheus
- mysql_exporter对接prometheus
bash
# monitor操作,打开文件,添加如下内容,注意对齐格式,# 注意:是监控机IP和Mysqld_exporter端口
[root@monitor ~]# vim /usr/local/prometheus/prometheus.yml
- job_name: "mysql"
static_configs:
- targets: ["192.168.56.144:9104"]
labels:
instance: mysqld_exporter
4.5.4 部署Grafana
-
Grafana是一个功能强大、灵活性高、易于使用的数据可视化和监控工具,广泛应用于IT运维、应用性能监控、工业物联网等领域
-
使用Grafana,用户可以轻松地创建各种图表、图形和面板,以直观和动态的方式展示数据趋势、指标和警报。其灵活的插件系统和丰富的图形化选项使用户能够根据自己的需求定制仪表板,并将其集成到现有的监控系统中

- 下载Grafana:
bash
[root@monitor ~]# yum install grafana-enterprise-11.1.2-1.x86_64.rpm -y
- 修改配置文件
bash
[root@monitor ~]# vim /etc/grafana/grafana.ini
################################# Server #################################
[server]
# Protocol (http, https, h2, socket)
protocol = http # 启用
# This is the minimum TLS version allowed. By default, this value is empty. Accepted values are: TLS1.2, TLS1.3. If nothing is set TLS1.2 would be taken
;min_tls_version = ""
# The ip address to bind to, empty will bind to all interfaces
;http_addr =
# The http port to use
http_port = 3000 # 启用
# The public facing domain name used to access grafana from a browser
domain = localhost # 启用
# Redirect to correct domain if host header does not match domain
# Prevents DNS rebinding attacks
;enforce_domain = false
# The full public facing url you use in browser, used for redirects and emails
# If you use reverse proxy and sub path specify full url (with sub path)
root_url = %(protocol)s://%(domain)s:%(http_port)s/ # 启用
- 启动
bash
[root@monitor ~]# systemctl enable --now grafana-server
[root@monitor ~]# systemctl status grafana-server
- 关联Promethues并设置仪表盘模版
bash
# 浏览器其中输入:http://192.168.56.144:3000
# 初始账户/密码:admin/admin
# 设置新的密码:123456
# 在设置界面中选择Home > Connections > Data sources > prometheus
# 设置prometheus监听地址:http://192.168.56.144:9090
# save&test
# 选择监控模版来显示mysql的关键指标,模版ID为7362

4.5.5 压力测试
-
查看VIP所在服务器,停止当前节点的mysql,查看VIP是否漂移,刷新监控界面,看是否高可用
-
MySQL自带的压力测试工具------Mysqlslap
bash
# 修改最大连接数
vim /etc/my.cnf
max_connections=1024
systemctl restart mysql
# 完成压测,查看仪表盘
mysqlslap --defaults-file=/etc/my.cnf --concurrency=200,400 --iterations=1 --number-int-cols=50 --number-char-cols=60 --auto-generate-sql --auto-generate-sql-add-autoincrement --auto-generate-sql-load-type=mixed --engine=innodb --number-of-queries=2000 -uroot -p123456 --verbose

至此该项目结束,成功搭建了mysql双主架构keepalived高可用集群+监控平台