rhel 8.7 部署 keepalived+haproxy 实现 mysql 双主高可用场景
文章目录
- @[toc]
- 部署 mysql
- 关闭防火墙
- 关闭 selinux
- 创建相关目录
- 创建 mysql 用户
- 配置 PATH 变量
- 验证 mysql 命令
- 切换到 mysql 用户
- 在 172.72.0.116 生成配置文件
- 在 172.72.0.137 生成配置文件
- mysql 初始化
- 启动 mysql 服务
- 修改 mysql 的 root 用户密码
- 配置主从关系
- 172.72.0.137 配置成 172.72.0.116 的从库
- 172.72.0.116 配置成 172.72.0.137 的从库
- 主从复制验证
- 部署 haproxy
- 创建 haproxy 配置文件
- 启动 haproxy
- 验证 haproxy 登录到 mysql
- 部署 keepalived
- Keepalived 工作原理
- 抢占和非抢占模式
- 在 172.72.0.116 创建 keepalived 配置文件
- 在 172.72.0.137 创建 keepalived 配置文件
- 配置 haproxy 健康检测脚本
- 启动 keepalived 服务
- 验证 VIP 登录 mysql
- 验证高可用是否有效
- 当一台 mysql 服务无进程
- 验证 keepalived 是否为非抢占模式
- 当一台 haproxy 服务无进程,mysql 服务均正常
文章目录
- @[toc]
- 部署 mysql
- 关闭防火墙
- 关闭 selinux
- 创建相关目录
- 创建 mysql 用户
- 配置 PATH 变量
- 验证 mysql 命令
- 切换到 mysql 用户
- 在 172.72.0.116 生成配置文件
- 在 172.72.0.137 生成配置文件
- mysql 初始化
- 启动 mysql 服务
- 修改 mysql 的 root 用户密码
- 配置主从关系
- 172.72.0.137 配置成 172.72.0.116 的从库
- 172.72.0.116 配置成 172.72.0.137 的从库
- 主从复制验证
- 部署 haproxy
- 创建 haproxy 配置文件
- 启动 haproxy
- 验证 haproxy 登录到 mysql
- 部署 keepalived
- Keepalived 工作原理
- 抢占和非抢占模式
- 在 172.72.0.116 创建 keepalived 配置文件
- 在 172.72.0.137 创建 keepalived 配置文件
- 配置 haproxy 健康检测脚本
- 启动 keepalived 服务
- 验证 VIP 登录 mysql
- 验证高可用是否有效
- 当一台 mysql 服务无进程
- 验证 keepalived 是否为非抢占模式
- 当一台 haproxy 服务无进程,mysql 服务均正常
话不多说,直接开搞
ip | 服务 |
---|---|
172.72.0.116 | keepalived+haproxy+mysql |
172.72.0.137 | keepalived+haproxy+mysql |
172.72.0.100 | VIP |
部署前,大家先要确认集群之间的时间是否一致,集群类的服务,最怕时间不一致
部署 mysql
- Mysql 二进制文件下载地址
部署相关的操作,两台机器都需要执行,需要执行指定机器时,会额外提示
关闭防火墙
systemctl disable firewalld --now
关闭 selinux
setenforce 0
sed -i '/SELINUX/s/enforcing/disabled/g' /etc/selinux/config
创建相关目录
mkdir -p /data/{software,mysql/{config,logs},script,mysql-back}
创建完成后的目录结构如下
/data/
├── mysql
│ ├── config
│ ├── logs
│ ├── mysql_data
├── mysql-back
├── script
└── software
解压下载好的二进制文件
tar xf mysql-5.7.29-linux-glibc2.12-x86_64.tar.gz
创建 mysql 用户
useradd mysql
# 配置用户密码
echo mysqldba | passwd --stdin mysql
给对应的目录和文件修改权限
chown -R mysql /data/software/mysql-5.7.29-linux-glibc2.12-x86_64
chown -R mysql /data/mysql
chown -R mysql /data/mysql-back
配置 PATH 变量
echo 'MYSQL_HOME="/data/software/mysql-5.7.29-linux-glibc2.12-x86_64"' >> /etc/profile
echo 'PATH=${PATH}:${MYSQL_HOME}/bin' >> /etc/profile
source /etc/profile
验证 mysql 命令
查看是否缺少依赖库
ldd /data/software/mysql-5.7.29-linux-glibc2.12-x86_64/bin/mysql
例如我这边缺了俩依赖
linux-vdso.so.1 (0x00007ffe91b5a000)libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f495203f000)librt.so.1 => /lib64/librt.so.1 (0x00007f4951e37000)libdl.so.2 => /lib64/libdl.so.2 (0x00007f4951c33000)libncurses.so.5 => not foundlibstdc++.so.6 => /lib64/libstdc++.so.6 (0x00007f495189e000)libm.so.6 => /lib64/libm.so.6 (0x00007f495151c000)libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007f4951304000)libc.so.6 => /lib64/libc.so.6 (0x00007f4950f3e000)/lib64/ld-linux-x86-64.so.2 (0x00007f495225f000)libtinfo.so.5 => not found
找一下是否有高版本的依赖
find / -type f -name "libncurses.so*"
尝试用软连接
ln -s /usr/lib64/libncurses.so.6.1 /usr/lib64/libncurses.so.5
再次使用上面的 ldd 命令去检查依赖,发现不是 not found 了,用这个办法,再去解决剩下的依赖缺失
验证 mysql 命令能不能正常使用
mysql -V
可以获取到当前的 mysql 客户端版本
mysql Ver 14.14 Distrib 5.7.29, for linux-glibc2.12 (x86_64) using EditLine wrapper
切换到 mysql 用户
后续的操作都使用 mysql 用户
su - mysql
在 172.72.0.116 生成配置文件
cat << EOF > /data/mysql/config/my.cnf
[mysqld]
pid-file=/data/mysql/mysqld.pid
socket=/data/mysql/mysqld.sock
datadir=/data/mysql/mysql_data
log-error=/data/mysql/logs/error.log
port=13306
# MySQL 在运行时需要 errmsg.sys 文件来显示和报告错误消息
lc-messages-dir=/data/software/mysql-5.7.29-linux-glibc2.12-x86_64/share/englishserver_id=116# binlog
# binlog 文件的名称
log_bin=mysql-bin
# 设置每个二进制日志文件的最大大小
max_binlog_size=100m
# 设置用于缓存二进制日志事件的缓冲区大小
binlog_cache_size=4m
# 设置 binlog 缓存的最大大小
max_binlog_cache_size=512m
# binlog 类型
binlog_format=MIXED
# binlog 过期时间
expire_logs_days=7bind-address=0.0.0.0
# 是否允许在数据库目录下使用符号链接
## symbolic-links=0:表示不允许使用符号链接。如果设置为 0,MySQL 服务器在启动时将不会使用数据库目录下的符号链接,并且可能会在符号链接存在时报错。
## symbolic-links=1:表示允许使用符号链接。如果设置为 1,MySQL 服务器在启动时将允许使用数据库目录下的符号链接,但仅限于特定目录或文件(根据权限设置)。
## symbolic-links=2:表示允许使用符号链接,且没有限制。如果设置为 2,MySQL 服务器在启动时将允许使用数据库目录下的任意符号链接,包括对任意文件或目录的链接。
symbolic-links=0
# mysql 最大连接数
max_connections=1000
# 默认存储引擎
default_storage_engine=innodb
# 禁用外部锁定,MySQL 将使用内部锁定来代替外部锁定
skip_external_locking
# 0:表名存储为原始大小写,区分大小写;
# 1:表名存储为小写,不区分大小写;
# 2:表名存储为小写,但会在文件系统上进行名称比较,因此会区分大小写。
lower_case_table_names=1
# 禁用主机缓存,每次都要重新解析域名
skip_host_cache
# 开启主机名解析
skip_name_resolve
# 设置服务器的默认字符集
character_set_server=utf8
# 客户端与服务器之间允许的最大数据包大小
max_allowed_packet=12M
# 控制 SQL 的执行模式
## STRICT_TRANS_TABLES:启用严格模式,对于事务表,如果有非法数据插入或更新,将会引发错误
## NO_ZERO_IN_DATE:禁止在日期中使用 "0000-00-00" 这样的零值,否则会被转换为 NULL 值
## ERROR_FOR_DIVISION_BY_ZERO:当除零错误发生时,产生错误而不是返回 NULL 值
## NO_AUTO_CREATE_USER:禁止 GRANT 语句自动创建新用户,必须手动创建
## NO_ENGINE_SUBSTITUTION:如果指定的存储引擎不可用或不存在,不要自动替换为其他可用的存储引擎,而应该返回错误
sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION'[client]
# 设置 MySQL 客户端连接的默认字符集
character-set-client=utf8
EOF
在 172.72.0.137 生成配置文件
cat << EOF > /data/mysql/config/my.cnf
[mysqld]
pid-file=/data/mysql/mysqld.pid
socket=/data/mysql/mysqld.sock
datadir=/data/mysql/mysql_data
log-error=/data/mysql/logs/error.log
port=13306
# MySQL 在运行时需要 errmsg.sys 文件来显示和报告错误消息
lc-messages-dir=/data/software/mysql-5.7.29-linux-glibc2.12-x86_64/share/englishserver_id=137# binlog
# binlog 文件的名称
log_bin=mysql-bin
# 设置每个二进制日志文件的最大大小
max_binlog_size=100m
# 设置用于缓存二进制日志事件的缓冲区大小
binlog_cache_size=4m
# 设置 binlog 缓存的最大大小
max_binlog_cache_size=512m
# binlog 类型
binlog_format=MIXED
# binlog 过期时间
expire_logs_days=7bind-address=0.0.0.0
# 是否允许在数据库目录下使用符号链接
## symbolic-links=0:表示不允许使用符号链接。如果设置为 0,MySQL 服务器在启动时将不会使用数据库目录下的符号链接,并且可能会在符号链接存在时报错。
## symbolic-links=1:表示允许使用符号链接。如果设置为 1,MySQL 服务器在启动时将允许使用数据库目录下的符号链接,但仅限于特定目录或文件(根据权限设置)。
## symbolic-links=2:表示允许使用符号链接,且没有限制。如果设置为 2,MySQL 服务器在启动时将允许使用数据库目录下的任意符号链接,包括对任意文件或目录的链接。
symbolic-links=0
# mysql 最大连接数
max_connections=1000
# 默认存储引擎
default_storage_engine=innodb
# 禁用外部锁定,MySQL 将使用内部锁定来代替外部锁定
skip_external_locking
# 0:表名存储为原始大小写,区分大小写;
# 1:表名存储为小写,不区分大小写;
# 2:表名存储为小写,但会在文件系统上进行名称比较,因此会区分大小写。
lower_case_table_names=1
# 禁用主机缓存,每次都要重新解析域名
skip_host_cache
# 开启主机名解析
skip_name_resolve
# 设置服务器的默认字符集
character_set_server=utf8
# 客户端与服务器之间允许的最大数据包大小
max_allowed_packet=12M
# 控制 SQL 的执行模式
## STRICT_TRANS_TABLES:启用严格模式,对于事务表,如果有非法数据插入或更新,将会引发错误
## NO_ZERO_IN_DATE:禁止在日期中使用 "0000-00-00" 这样的零值,否则会被转换为 NULL 值
## ERROR_FOR_DIVISION_BY_ZERO:当除零错误发生时,产生错误而不是返回 NULL 值
## NO_AUTO_CREATE_USER:禁止 GRANT 语句自动创建新用户,必须手动创建
## NO_ENGINE_SUBSTITUTION:如果指定的存储引擎不可用或不存在,不要自动替换为其他可用的存储引擎,而应该返回错误
sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION'[client]
# 设置 MySQL 客户端连接的默认字符集
character-set-client=utf8
EOF
mysql 初始化
mysqld --initialize-insecure \
--user=mysql \
--basedir=${MYSQL_HOME} \
--datadir=/data/mysql/mysql_data
启动 mysql 服务
${MYSQL_HOME}/bin/mysqld \
--defaults-file=/data/mysql/config/my.cnf --daemonize \
--plugin-dir=${MYSQL_HOME}/lib/plugin
修改 mysql 的 root 用户密码
进入 mysql,初始化的时候没有设定密码,直接回车就可以了
mysql -uroot -p -S /data/mysql/mysqld.sock
修改密码
SET PASSWORD FOR root@localhost = PASSWORD ('YWJjMTIzCg==');
配置主从关系
以下的配置,都是基于新部署的数据库实现的,如果当前数据库本身存在数据的情况下,需要先把 master 的数据备份,然后在 slave 节点上恢复数据后,再进行主从配置
172.72.0.137 配置成 172.72.0.116 的从库
在 172.72.0.116 的 mysql 里面操作,创建一个从复制专用的用户
CREATE USER 'rpldb'@'%' IDENTIFIED BY 'cnBsZGIwMDcK';
GRANT REPLICATION SLAVE ON *.* TO 'rpldb'@'%';
查看 binlog 的文件名称和 Position 信息
SHOW MASTER STATUS\G
获取到类似如下的信息
*************************** 1. row ***************************File: mysql-bin.000001Position: 841Binlog_Do_DB:Binlog_Ignore_DB: sys,mysql,performance_schema,information_schema
Executed_Gtid_Set:
1 row in set (0.00 sec)
在 172.72.0.137 的 mysql 里面操作
CHANGE MASTER TO MASTER_HOST='172.72.0.116', MASTER_PORT=13306, MASTER_USER='rpldb', MASTER_PASSWORD='cnBsZGIwMDcK', MASTER_LOG_FILE='mysql-bin.000001', MASTER_LOG_POS=841;
启动复制
STOP SLAVE;
START SLAVE;
查看复制是否成功
SHOW SLAVE STATUS\G
看到这两个都是 yes,表示主从复制已经建立成功了
Slave_IO_Running: YesSlave_SQL_Running: Yes
172.72.0.116 配置成 172.72.0.137 的从库
在 172.72.0.137 的 mysql 里面操作,创建一个从复制专用的用户
CREATE USER 'rpldb'@'%' IDENTIFIED BY 'cnBsZGIwMDcK';
GRANT REPLICATION SLAVE ON *.* TO 'rpldb'@'%';
查看 binlog 的文件名称和 Position 信息
SHOW MASTER STATUS\G
获取到类似如下的信息
*************************** 1. row ***************************File: mysql-bin.000001Position: 841Binlog_Do_DB:Binlog_Ignore_DB: sys,mysql,performance_schema,information_schema
Executed_Gtid_Set:
1 row in set (0.00 sec)
在 172.72.0.116 的 mysql 里面操作
CHANGE MASTER TO MASTER_HOST='172.72.0.137', MASTER_PORT=13306, MASTER_USER='rpldb', MASTER_PASSWORD='cnBsZGIwMDcK', MASTER_LOG_FILE='mysql-bin.000001', MASTER_LOG_POS=841;
启动复制
STOP SLAVE;
START SLAVE;
查看复制是否成功
SHOW SLAVE STATUS\G
看到这两个都是 yes,表示主从复制已经建立成功了
Slave_IO_Running: YesSlave_SQL_Running: Yes
主从复制验证
- 先使用 mysql root 用户创建一个库
create database music;
再创建一个 mysql 的普通用户,并且对 music 库有增改查的权限
CREATE USER 'vinci'@'%' IDENTIFIED BY 'DavVinci';
GRANT SELECT,UPDATE,INSERT,CREATE ON music.* TO 'vinci'@'%';
使用 vinci 用户登录到 172.72.0.116 的 mysql,进行建库建表
CREATE TABLE music.favorite(name char(10),music_name char(20)
)charset=utf8;
插入几条数据
INSERT INTO music.favorite(name, music_name) VALUES
('Eason Chan','遥远的她'),
('Ronald','怪胎'),
('Hacken Lee','李香兰');
使用 vinci 用户登录到 172.72.0.137 的 mysql,查看数据是否存在
SELECT music_name FROM music.favorite WHERE name='Ronald' limit 5;
部署 haproxy
- 官网:http://www.haproxy.com
- HAProxy提供高可用性、负载均衡以及基于TCP和HTTP的应用代理,支持虚拟主机,它是免费、快速并且可靠的一种负载均衡解决方案。适合处理高负载站点的七层数据请求。类似的代理服务可以屏蔽内部真实服务器,防止内部服务器遭受攻击。
使用 yum 安装
yum install -y haproxy
创建 haproxy 配置文件
备份原来的配置文件
cp /etc/haproxy/haproxy.cfg{,.bak}
创建配置文件
cat << EOF > /etc/haproxy/haproxy.cfg
global log 127.0.0.1 local3 info # 在本机记录日志maxconn 65535 # 每个进程可用的最大连接数chroot /data/haproxy # haproxy 安装目录pidfile /data/haproxy/haproxy.pid # haproxy pid 文件目录uid 994 # 运行 haproxy 的用户uid(id haproxy 命令可以查看)gid 991 # 运行 haproxy 的用户组id(id haproxy 命令可以查看)daemon # 以后台守护进程运行defaultslog globalmode http # 运行模式 tcp、 http、 healthretries 3 # 三次连接失败,则判断服务不可用option redispatch # 如果后端有服务器宕机,强制切换到正常服务器stats uri /haproxy # 统计页面 URL 路径stats refresh 30s # 统计页面自动刷新时间stats realm haproxy-status # 统计页面输入密码框提示信息stats auth admin:YWJjMTIzCg== # 统计页面用户名和密码stats hide-version # 隐藏统计页面上 HAProxy 版本信息maxconn 65535 # 每个进程可用的最大连接数timeout connect 5000 # 连接超时 timeout client 50000 # 客户端超时timeout server 50000 # 服务器端超时frontend http_haproxymode http # 运行模式 tcp、 http、 healthmaxconn 65535 # 每个进程可用的最大连接数bind :18080 # 监听 18080 端口log global option httplog option httpclose # 每次请求完毕后主动关闭 http 通道frontend mysqls # 自定义描述信息mode tcp # 运行模式 tcp、 http、 healthmaxconn 65535 # 每个进程可用的最大连接数bind *:13307 # 监听 13307 端口default_backend mysql_backendbackend mysql_backendmode tcpbalance roundrobin # 设置负载均衡模式,source 保存 session 值,roundrobin 轮询模式# rise 2是2次正确认为服务器可用# fall 3是3次失败认为服务器不可用server mysql01 172.72.0.116:13306 check inter 5s rise 2 fall 3server mysql02 172.72.0.137:13306 check inter 5s rise 2 fall 3
EOF
给 haproxy 的 chroot 目录授权
mkdir /data/haproxy
chown -R haproxy /data/haproxy
启动 haproxy
systemctl enable haproxy
systemctl start haproxy
可以在浏览器输入
172.72.0.116:18080/haproxy
或者172.72.0.137:18080/haproxy
来验证是否可以看到统计页面,这里的 ip,大家以自己实际的为准
验证 haproxy 登录到 mysql
haproxy 正确的情况下,两个地址都可以用 13307 端口来登录到 mysql 内
mysql -uvinci -pDavVinci -h172.72.0.116 -P13307
mysql -uvinci -pDavVinci -h172.72.0.137 -P13307
部署 keepalived
Keepalived 工作原理
-
keepalived 是以 VRRP 协议为实现基础的,VRRP 全称 Virtual Router Redundancy Protocol ,即虚拟路由冗余协议。
- 虚拟路由冗余协议,可以认为是实现路由器高可用的协议。也就是说N台提供相同功能的路由器组成一个路由器组,这个组里面有一个 master 和多个 backup,master上面有一个对外提供服务的vip,master 不断向 backup 发送心跳信息,告诉 backup 自己还活着,当 backup 收不到心跳消息时就认为 master 已经宕机啦,这时就需要根据 VRRP 的优先级来选举一个 backup 当 master。从而保证高可用。
-
keepalived主要有三个模块,分别是 core、check 和 vrrp。
- core 模块为 keepalived 的核心,负责主进程的启动、维护、以及全局配置文件的加载和解析。
- check 负责健康检查,包括常见的各种检查方式。
- vrrp 模块是来实现 VRRP 协议的。
-
vrrp 虚拟路由冗余协议
- 使用ip报文作为传输协议;
- 协议号112;
- 使用固定组播网络 224.0.0.18 进行发送;
- 只是用advertisement报文;
-
master路由器的选举:
- 比较每台路由器设备的优先级,优先级大的为 master。优先级相同的,比较接口IP地址,地址大的成为 master;
- master 会主动周期的发送 advertisement 报文,一秒发送一次;
- backup 如果 3 秒没有接到 master 发送的 advertisment 报文,就说明 master down;
抢占和非抢占模式
摘抄自:MySQL + Keepalived 双主热备高可用操作记录
keepalive 通过组播,单播等方式(自定义),实现 keepalive 主备推选。工作模式分为抢占和非抢占(通过参数 nopreempt 来控制)。
-
抢占模式
:- 主服务正常工作时,虚拟 IP 会在主上,备不提供服务,当主服务优先级低于备的时候,备会自动抢占虚拟 IP,这时,主不提供服务,备提供服务。
也就是说,工作在抢占模式下,不分主备,只管优先级。 - 不管 keepalived.conf 里的 state 配置成 master 还是 backup,只看谁的 priority 优先级高(一般而言,state 为 MASTER 的优先级要高于 BACKUP)。priority 优先级高的那一个在故障恢复后,会自动将 VIP 资源再次抢占回来!!
- 主服务正常工作时,虚拟 IP 会在主上,备不提供服务,当主服务优先级低于备的时候,备会自动抢占虚拟 IP,这时,主不提供服务,备提供服务。
-
非抢占模式:
- 这种方式通过参数 nopreempt(一般设置在 advert_int 的那一行下面)来控制。不管 priority 优先级,只要 MASTER 机器发生故障,VIP 资源就会被切换到 BACKUP 上。
并且当 MASTER 机器恢复后,也不会去将 VIP 资源抢占回来,直至 BACKUP 机器发生故障时,才能自动切换回来。
- 这种方式通过参数 nopreempt(一般设置在 advert_int 的那一行下面)来控制。不管 priority 优先级,只要 MASTER 机器发生故障,VIP 资源就会被切换到 BACKUP 上。
千万注意
:
nopreempt 这个参数只能用于 state 为 backup 的情况,所以在配置的时候要把 master 和 backup 的 state 都设置成 backup,这样才会实现 keepalived 的非抢占模式!
也就是说:
- 当 state 状态一个为 master,一个为 backup 的时候,加不加 nopreempt 这个参数都是一样的效果。即都是根据 priority 优先级来决定谁抢占 vip 资源的,是抢占模式!
- 当 state 状态都设置成 backup,如果不配置 nopreempt 参数,那么也是看 priority 优先级决定谁抢占 vip 资源,即也是抢占模式。
- 当 state 状态都设置成 backup,如果配置 nopreempt 参数,那么就不会去考虑 priority 优先级了,是非抢占模式!即只有 vip 当前所在机器发生故障,另一台机器才能接管 vip。即使优先级高的那一台机器恢复 后也不会主动抢回 vip,只能等到对方发生故障,才会将 vip 切回来。
使用 yum 安装
yum install -y keepalived
在 172.72.0.116 创建 keepalived 配置文件
备份原来的配置文件
cp /etc/keepalived/keepalived.conf{,.bak}
创建配置文件,这里采用非抢占模式
cat << EOF > /etc/keepalived/keepalived.conf
! Configuration File for keepalivedglobal_defs {# 每个 keepalived 要配置成不一样的router_id mysql1
}# 作用:添加一个周期性执行的脚本。
## 脚本的退出状态码会被调用它的所有的VRRP Instance记录。
## 注意:至少有一个VRRP实例调用它并且优先级不能为0。
## 优先级范围是1-254,用来做健康检查的,当检查失败时会将 vrrp_instance 的 priority 减少相应的值
vrrp_script chk_haproxy {# 监控服务脚本,脚本x执行权限;script "/data/script/chk_haproxy.sh"# 检测时间间隔(执行脚本间隔)interval 2weight -2# 解释 weight:## 如果脚本执行成功(退出状态码为0),weight大于0,则priority增加。## 如果脚本执行失败(退出状态码为非0),weight小于0,则priority减少。## 其他情况下,priority不变。
}vrrp_instance VI_1 {state BACKUP# 指定虚拟 ip 的网卡接口,根据自己实际网卡名称修改interface ens160# 路由器标识,MASTER 和 BACKUP 必须是一致的virtual_router_id 51# 定义优先级,数字越大,优先级越高,在同一个 vrrp_instance 下,MASTER 的优先级必须大于 BACKUP 的优先级。这样 MASTER 故障恢复后,就可以将VIP资源再次抢回来priority 100advert_int 1authentication {auth_type PASSauth_pass 1111}virtual_ipaddress {172.72.0.100}# 添加此行表示非抢占模式# nopreempttrack_script {chk_haproxy}
}
EOF
在 172.72.0.137 创建 keepalived 配置文件
备份原来的配置文件
cp /etc/keepalived/keepalived.conf{,.bak}
创建配置文件,这里采用非抢占模式
cat << EOF > /etc/keepalived/keepalived.conf
! Configuration File for keepalivedglobal_defs {# 每个 keepalived 要配置成不一样的router_id mysql2
}# 作用:添加一个周期性执行的脚本。
## 脚本的退出状态码会被调用它的所有的VRRP Instance记录。
## 注意:至少有一个VRRP实例调用它并且优先级不能为0。
## 优先级范围是1-254,用来做健康检查的,当检查失败时会将 vrrp_instance 的 priority 减少相应的值
vrrp_script chk_haproxy {# 监控服务脚本,脚本x执行权限;script "/data/script/chk_haproxy.sh"# 检测时间间隔(执行脚本间隔)interval 2weight -2# 解释 weight:## 如果脚本执行成功(退出状态码为0),weight大于0,则priority增加。## 如果脚本执行失败(退出状态码为非0),weight小于0,则priority减少。## 其他情况下,priority不变。
}vrrp_instance VI_1 {state BACKUP# 指定虚拟 ip 的网卡接口,根据自己实际网卡名称修改interface ens160# 路由器标识,MASTER 和 BACKUP 必须是一致的virtual_router_id 51# 定义优先级,数字越大,优先级越高,在同一个 vrrp_instance 下,MASTER 的优先级必须大于 BACKUP 的优先级。这样 MASTER 故障恢复后,就可以将VIP资源再次抢回来priority 100advert_int 1authentication {auth_type PASSauth_pass 1111}virtual_ipaddress {172.72.0.100}# 添加此行表示非抢占模式# nopreempttrack_script {chk_haproxy}
}
EOF
配置 haproxy 健康检测脚本
- 所有 keepalived 节点都需要配置
- 因为非抢占模式,所以需要手动切换 VIP,这里脚本用停止 keepalived 服务来触发手动切换 VIP
- 脚本里面是探测 haproxy 的端口三次,如果返回状态码都是非0,就会触发停止 keepalived 服务
cat << EOF > /data/script/chk_haproxy.sh
#!/bin/bash
exitNum=0while true
doif ! nc -z 127.0.0.1 13307; thenlet exitNum++[ ${exitNum} -lt 3 ] || systemctl stop keepalivedfi
done
EOF
keepalived 的健康检测脚本必须要有执行权限
chmod +x /data/script/chk_haproxy.sh
启动 keepalived 服务
注意启动顺序,要先启动一个 keepalived 组件,并且有 VIP 了之后,再去启动剩下的 keepalived 组件,如果同时启动 keepalived 组件,那就都会有 VIP 地址了
systemctl enable keepalived
systemctl start keepalived
验证 VIP 登录 mysql
能读取到数据,证明 keepalived 部署没有问题
mysql -uvinci -pDavVinci -h172.72.0.100 -P13307 -e "SELECT music_name FROM music.favorite WHERE name='Hacken Lee' limit 1;"
验证高可用是否有效
当一台 mysql 服务无进程
- 杀掉一个 mysql 的进程,模拟 mysql 出现故障,等 30秒后,看是否能写入 mysql 数据
- 杀掉一个 mysql 的进程后,可以从 haproxy 的统计页面看到显示为 down
cat /data/mysql/mysqld.pid | xargs kill -9 && \
sleep 30 && \
mysql -uvinci -pDavVinci -h172.72.0.100 -P13307 -e "INSERT INTO music.favorite(name, music_name) VALUES ('Beyond','冷雨夜');"
验证完成后,再次启动 mysql,在 haproxy 的统计页面看到显示为 up,并且进入 mysql 查看
SHOW SLAVE STATUS
确认Slave_IO_Running
和Slave_SQL_Running
都是YES
验证 keepalived 是否为非抢占模式
存在 VIP 的节点,停止 keepalived 服务,模拟 keepalived 故障,看 VIP 是否会漂移到其他节点
systemctl stop keepalived
此时去其他节点,发现 VIP 已经漂移过来了,并且可以读取 mysql 数据
- 将停止的 keepalived 重新启动,看 VIP 是否会漂移回来
- 正常情况下,处于非抢占模式,VIP 是不会再次漂移的
systemctl start keepalived
当一台 haproxy 服务无进程,mysql 服务均正常
- 这里直接把有 VIP 节点的 haproxy 服务停止,模拟 haproxy 故障,并且触发 keepalived 的健康检测,进行 VIP 的漂移,同时验证是否能读取 mysql 数据
systemctl stop haproxy && \
sleep 10 && \
ip a | grep 172.72.0.100; \
mysql -uvinci -pDavVinci -h172.72.0.100 -P13307 -e "SELECT music_name FROM music.favorite WHERE name='Hacken Lee' limit 1;"
使用 tcpdump 命令观察地址的变化
tcpdump -i ens160 vrrp -nn
可以看到,VIP 从 172.72.0.116 机器切换到 172.72.0.137 机器上,并且也能正常读取 mysql 的数据
22:25:19.569090 IP 172.72.0.116 > 224.0.0.18: VRRPv2, Advertisement, vrid 51, prio 98, authtype simple, intvl 1s, length 20
22:25:20.569328 IP 172.72.0.116 > 224.0.0.18: VRRPv2, Advertisement, vrid 51, prio 98, authtype simple, intvl 1s, length 20
22:25:21.570001 IP 172.72.0.116 > 224.0.0.18: VRRPv2, Advertisement, vrid 51, prio 98, authtype simple, intvl 1s, length 20
22:25:21.578036 IP 172.72.0.116 > 224.0.0.18: VRRPv2, Advertisement, vrid 51, prio 0, authtype simple, intvl 1s, length 20
22:25:22.196273 IP 172.72.0.137 > 224.0.0.18: VRRPv2, Advertisement, vrid 51, prio 98, authtype simple, intvl 1s, length 20
22:25:23.196572 IP 172.72.0.137 > 224.0.0.18: VRRPv2, Advertisement, vrid 51, prio 98, authtype simple, intvl 1s, length 20
22:25:24.196795 IP 172.72.0.137 > 224.0.0.18: VRRPv2, Advertisement, vrid 51, prio 98, authtype simple, intvl 1s, length 20
基于二进制部署的 mysql 写了一个脚本来做启停和重启
#!/usr/bin/env bash
baseDir="$(cd `dirname $0`;pwd)"
envName="$1"
envOpt="$2"
pidFile="/data/mysql/mysqld.pid"
MYSQL_HOME='/data/software/mysql-5.7.29-linux-glibc2.12-x86_64'function opt_usage () {echo "usage: bash $0 'start|stop|restart'"exit 1
}if [ $# -lt 1 ];thenopt_usageexit 1
fifunction start_mysql () {if [[ ! -f "${pidFile}" ]];then${MYSQL_HOME}/bin/mysqld \--defaults-file=/data/mysql/config/my.cnf --daemonize \--plugin-dir=${MYSQL_HOME}/lib/pluginif [ $? -eq 0 ];thenecho "mysql start success"fielsepidNum=$(ps -ef | grep -v grep | grep mysqld | awk '{print $2}')echo "pid: ${pidNum} is running for mysqld,please check it"exit 1fi
}function stop_mysql () {if [[ ! -f "${pidFile}" ]];thenecho "pid file: ${pidFile} is not found"exit 1elsekill $(cat ${pidFile})sleep 5num=0while truedops -ef | grep -v grep | grep mysqld | awk '{print $2}' &> /dev/nullif [ $? -eq 0 ];thenecho "stop mysql success"breakelseecho "wating for mysql shutdown......"let num++sleep 1fiif [ ${num} -eq 3 ];thenecho "stop mysql failed,please check it"exit 1fidonefi
}function status_mysql () {if [ -f "${pidFile}" ];thenpidNum="$(ps -ef | grep -v grep | grep mysqld | awk '{print $2}')"if [ ${pidNum} -eq $(cat ${pidFile}) ];thenecho "mysql is running"echo "mysql version is: $(mysql -V)"echo " mysql pid is: ${pidNum}"fielseecho "mysql is not running"fi
}case $1 in'start')start_mysql;;'stop')stop_mysql;;'restart')stop_mysqlstart_mysql;;'status')status_mysql;;'*')opt_usageexit 1
esac
相关文章:
rhel 8.7 部署 keepalived+haproxy 实现 mysql 双主高可用场景
文章目录 [toc]部署 mysql关闭防火墙关闭 selinux创建相关目录创建 mysql 用户配置 PATH 变量验证 mysql 命令切换到 mysql 用户在 172.72.0.116 生成配置文件在 172.72.0.137 生成配置文件mysql 初始化启动 mysql 服务修改 mysql 的 root 用户密码配置主从关系172.72.0.137 配…...

常见指令以及权限理解
常见指令以及权限理解 命令格式: command [-options] parameter1 parameter1 命令 选项 参数1 参数2 1.command为命令名称,例如变化目录的cd等 2.中括号[ ]实际在命令中是不存在的,这个中括号代表可选,通常选项前面会添加一个符号…...

OpenCV基础知识(6)— 滤波器
前言:Hello大家好,我是小哥谈。在尽量保留原图像信息的情况下,去除图像内噪声、降低细节层次信息等一系列过程,被叫做图像的平滑处理(或者叫图像的模糊处理)。实现平滑处理最常用的工具就是滤波器。通过调节…...
IOC容器的基础功能设计模式
构造模式 构造器的目的和构造函数一样,但是构造器可以提供丰富的api来简化对象的构造 构造模式用于简化被构造对象的创建,通过提供一大堆的api来丰富简化构造过程,增加调用者的体验。 构造者需要提供一个Build方法用于构建和返回将要构造的…...
FFmpeg参数说明FFmpegAndroid饺子视频播放器
FFmpegAndroid https://github.com/xufuji456/FFmpegAndroid https://github.com/lipangit/JiaoZiVideoPlayer/tree/develop 饺子视频播放器 ffmpeg 不是内部或外部命令,也不是可运行的程序 或批处理文件 http://www.360doc.com/content/21/0204/15/54508727_9606…...
DNS入门学习:DNS解析生效问题(中科三方)
在修改域名解析记录或DNS服务器之后,DNS解析并不会立即生效,这给很多网站管理者带来了很多困扰,了解DNS解析生效原理以及不同情况下DNS解析生效时间,对于网站管理工作有很大帮助。本文中科三方针对不同情况下DNS解析生效时间做下简…...
Ubuntu22.04编译安装Mysql5.7.35
新升级的ubuntu22.04版本,该版本默认openssl已经升级到3.0,所以编译过程遇到一些问题记录一下。 编译步骤: 安装依赖 gcc g已经安装过就不需要再安装了。 apt-get install cmake apt-get install libaio-dev apt-get install libncurses5…...

C++音乐播放系统
C音乐播放系统 音乐的好处c发出声音乐谱与赫兹对照把歌打到c上 学习c的同学们都知道,c是一个一本正经的编程语言,因该没有人用它来做游戏、做病毒、做…做…做音乐播放系统吧!! 音乐的好处 提升情绪:音乐能够影响我们…...
Django笔记之log日志记录详解
以下是一个简单的 logging 模块示例,可以先预览一下,接下来会详细介绍各个模块的具体功能: LOGGING {version: 1,disable_existing_loggers: False,formatters: {verbose: {format: %(levelname)s %(message)s,}},handlers: {file_1: {leve…...
vue局部打印多页面pdf
技术背景 html打印程pdf,使用的官方提供的window.print()打印的样式 media print {} 方法一 const printContent this.$refs.bodyright;var textInput printContent.getElementsByTagName("input");for (var i 0; i < textInput.length; i) {textInput[i].se…...
指定或降低Rust 工具链的版本
要更改 Rust 工具链的版本,您可以使用以下命令之一: rustup default stable:使用 stable 版本的 Rust 工具链作为默认版本。rustup default beta:使用 beta 版本的 Rust 工具链作为默认版本。rustup default nightly:使…...
数据驱动成功:商城小程序分析与改进
在当今数字化时代,商城小程序成为了企业与消费者之间互动的重要途径。然而,一个成功的商城小程序不仅仅是一个购物平台,更需要通过数据分析不断进行改进和优化,以提升用户体验和营销效果。本文将深入探讨如何利用数据驱动的方式进…...

基于GUI的卷积神经网络和长短期神经网络的语音识别系统,卷积神经网的原理,长短期神经网络的原理
目录 背影 卷积神经网络CNN的原理 卷积神经网络CNN的定义 卷积神经网络CNN的神经元 卷积神经网络CNN的激活函数 卷积神经网络CNN的传递函数 长短期神经网络的原理 基于GUI的卷积神经网络和长短期神经网络的语音识别系统 代码下载链接:基于MATLABGUI编程的卷积神经网络和长短期…...

Docker环境安装elasticsearch和kibana
一、安装elasticsearch 创建es-network,让es、kibana在同一个网段: docker network create --driverbridge --subnet192.168.1.10/24 es-network运行elasticsearch docker run -d \ --name elasticsearch \ # 容器名 --hostname elasticsearch # 主机…...

【剖析STL】vector
vector的介绍及使用 1.1 vector的介绍 cplusplus.com/reference/vector/vector/ vector是表示可变大小数组的序列容器。就像数组一样,vector也采用的连续存储空间来存储元素。也就是意味着可以采用下标对vector的元素 进行访问,和数组一样高效。但是…...

Redis、Memcache和MongoDB的区别
>>Memcached Memcached的优点: Memcached可以利用多核优势,单实例吞吐量极高,可以达到几十万QPS(取决于key、value的字节大小以及服务器硬件性能,日常环境中QPS高峰大约在4-6w左右)。适用于最大程度…...
2023中大ACM游记
游记 中午快十二点时才到了广州六中,在附近吃了塔斯汀汉堡,味道还不错。 十二点半才卡点到了考场,本以为来晚了,但老师说比赛时间延迟,十二点五十才开场。 三个人用一台电脑,这种比赛方式还是第一次遇到…...
记一次线上OOM事故
OOM 问题 linux内核有个机制叫OOM killer(Out-Of-Memory killer),当系统需要申请内存却申请不到时,OOM killer会检查当前进程中占用内存最大者,将其杀掉,腾出内存保障系统正常运行。 一般而言,一个应用的内存逐渐增加&…...

Learning to Super-resolve Dynamic Scenes for Neuromorphic Spike Camera论文笔记
摘要 脉冲相机使用了“integrate and fire”机制来生成连续的脉冲流,以极高的时间分辨率来记录动态光照强度。但是极高的时间分辨率导致了受限的空间分辨率,致使重建出的图像无法很好保留原始场景的细节。为了解决这个问题,这篇文章提出了Sp…...

怎么使用手机远程控制Win10电脑?
可以使用手机远程控制电脑吗? “近期,我将出差一段时间。问题是,我希望能够从很远的地方浏览家里电脑上的一些东西,但我不会一直随身携带笨重的笔记本电脑。我可以手机远程访问Windows电脑吗? ” 当然&am…...

Qt/C++开发监控GB28181系统/取流协议/同时支持udp/tcp被动/tcp主动
一、前言说明 在2011版本的gb28181协议中,拉取视频流只要求udp方式,从2016开始要求新增支持tcp被动和tcp主动两种方式,udp理论上会丢包的,所以实际使用过程可能会出现画面花屏的情况,而tcp肯定不丢包,起码…...
树莓派超全系列教程文档--(62)使用rpicam-app通过网络流式传输视频
使用rpicam-app通过网络流式传输视频 使用 rpicam-app 通过网络流式传输视频UDPTCPRTSPlibavGStreamerRTPlibcamerasrc GStreamer 元素 文章来源: http://raspberry.dns8844.cn/documentation 原文网址 使用 rpicam-app 通过网络流式传输视频 本节介绍来自 rpica…...
C++:std::is_convertible
C++标志库中提供is_convertible,可以测试一种类型是否可以转换为另一只类型: template <class From, class To> struct is_convertible; 使用举例: #include <iostream> #include <string>using namespace std;struct A { }; struct B : A { };int main…...

React第五十七节 Router中RouterProvider使用详解及注意事项
前言 在 React Router v6.4 中,RouterProvider 是一个核心组件,用于提供基于数据路由(data routers)的新型路由方案。 它替代了传统的 <BrowserRouter>,支持更强大的数据加载和操作功能(如 loader 和…...
什么?连接服务器也能可视化显示界面?:基于X11 Forwarding + CentOS + MobaXterm实战指南
文章目录 什么是X11?环境准备实战步骤1️⃣ 服务器端配置(CentOS)2️⃣ 客户端配置(MobaXterm)3️⃣ 验证X11 Forwarding4️⃣ 运行自定义GUI程序(Python示例)5️⃣ 成功效果
技术栈RabbitMq的介绍和使用
目录 1. 什么是消息队列?2. 消息队列的优点3. RabbitMQ 消息队列概述4. RabbitMQ 安装5. Exchange 四种类型5.1 direct 精准匹配5.2 fanout 广播5.3 topic 正则匹配 6. RabbitMQ 队列模式6.1 简单队列模式6.2 工作队列模式6.3 发布/订阅模式6.4 路由模式6.5 主题模式…...

Docker 本地安装 mysql 数据库
Docker: Accelerated Container Application Development 下载对应操作系统版本的 docker ;并安装。 基础操作不再赘述。 打开 macOS 终端,开始 docker 安装mysql之旅 第一步 docker search mysql 》〉docker search mysql NAME DE…...

浪潮交换机配置track检测实现高速公路收费网络主备切换NQA
浪潮交换机track配置 项目背景高速网络拓扑网络情况分析通信线路收费网络路由 收费汇聚交换机相应配置收费汇聚track配置 项目背景 在实施省内一条高速公路时遇到的需求,本次涉及的主要是收费汇聚交换机的配置,浪潮网络设备在高速项目很少,通…...
Java求职者面试指南:Spring、Spring Boot、Spring MVC与MyBatis技术解析
Java求职者面试指南:Spring、Spring Boot、Spring MVC与MyBatis技术解析 一、第一轮基础概念问题 1. Spring框架的核心容器是什么?它的作用是什么? Spring框架的核心容器是IoC(控制反转)容器。它的主要作用是管理对…...