Author:Arsen
Date:2024/06/25
目录
- 一、前言
- 1.1 概述
- 1.2 组件
- 1.3 流程
- 二、环境
- 三、部署
- 3.1 基本环境
- 3.1.1 hosts 配置
- 3.1.2 配置 SSH 免密访问
- 3.2 MySQL 主从
- 3.2.1 基础环境配置
- 3.2.2 启动 MySQL 实例
- 3.2.3 配置 MySQL 主从
- 3.2.4 MySQL 主从同步验证
- 3.3 MHA 部署
- 3.3.1 MHA node
- 3.3.2 MHA manager
- 3.4 MHA 配置
- 3.4.1 为 MHA 创建一个帐户
- 3.4.2 mha-manager 创建配置文件
- 3.4.3 mysql-slave 中继日志关闭自动清除
- 3.4.4 mysql-master 启用 VIP
- 3.5 MHA 可用性测试
- 3.5.1 测试 ssh 免密认证
- 3.5.2 测试 mysql 主从状态
- 3.6 启动 MHA
- 四、故障模拟与恢复
- 4.1 故障
- 4.2 恢复
- 五、应用程序如何连接?
- 总结
- 附件
一、前言
MHA官网:https://code.google.com/archive/p/mysql-master-ha/
GitHub地址:https://github.com/yoshinorim/mha4mysql-manager
文档:https://github.com/yoshinorim/mha4mysql-manager/wiki
1.1 概述
MySQL 高可用性工具集(MySQL High Availability Toolkit,简称 MHA)是一个用于管理 MySQL 主从复制环境的工具集。它旨在提供自动化的故障检测和故障转移,以确保 MySQL 环境的高可用性和可靠性,MHA 的工作原理涉及以下关键步骤:
-
MySQL 复制拓扑监控
MHA 通过检查 Master 节点和 Slave 节点之间的复制状态来监控 MySQL 复制拓扑,它可以定期查询MySQL服务器的状态,包括主节点的 Binlog 位置和从节点的复制延迟等信息。
-
故障检测
当 MHA 检测到主节点故障或者其他故障情况时,它会触发故障转移过程。这可能是由于 MySQL 服务器崩溃、网络中断、复制延迟等原因。
-
自动故障转移
在发生故障时,MHA会自动选择一个最适合的从节点,并将其提升为新的主节点。它会自动更新其他从节点的配置,以将它们重新连接到新的主节点。这确保了服务的连续性,并最大限度地减少了服务中断时间。
-
触发故障转移的条件
MHA 根据一定的条件来触发故障转移,例如:主节点失去连接、主节点的复制延迟超过预设的阈值、主节点上的 MySQL 进程崩溃、管理员手动触发故障转移。
-
健康检查和维护
MHA 定期执行健康检查,并处理发现的问题。它可以检测到从节点的延迟、复制错误等,并采取适当的措施来解决问题,以确保环境的稳定性和可靠性。
-
自定义配置和脚本
MHA 允许管理员根据实际需求定制各种配置选项和脚本。这使得 MHA 可以适应不同的环境和应用场景,并提供更灵活的管理和监控功能。
MHA 能做到在 0~30 秒之内自动完成数据库的故障切换操作,并且在进行故障切换的过程中,MHA能在最大程度上保证数据的一致性,以达到真正意义上的高可用。
1.2 组件
MHA主要由以下几个组件组成:
-
MHA Manager
运行在独立的管理服务器上,负责监控主库状态并在主库故障时执行自动故障切换。
-
MHA Node
部署在每个MySQL服务器上(包括主库和从库),负责管理MySQL服务器上的数据复制和日志处理。
-
SSH
用于各个节点之间的通信和命令执行。
-
Replication Configuration
MHA依赖于MySQL的复制机制,需要事先配置好主从复制。
1.3 流程
-
监控主库
MHA Manager 持续监控主库的状态,通过检查复制状态、主库可达性等指标来判断主库是否健康。
-
检测到主库故障
一旦 MHA Manager 检测到主库故障,它会立即暂停所有从库的复制进程,防止从库继续接收可能损坏的数据。
-
选择新的主库
MHA Manager 从可用的从库中选择一个延迟最小的从库作为新的主库候选。
MHA Manager 会检查每个从库的二进制日志,以确保数据的完整性和一致性。
-
应用中继日志
MHA Node 会在新的主库候选上应用所有未处理的中继日志,以确保新主库的数据与故障主库的数据一致。
如果中继日志不完整,MHA会尝试从其他从库中恢复丢失的二进制日志。
-
切换角色
MHA Manager 更新复制配置,使得其他从库开始从新的主库进行复制。
更新应用程序的连接信息,使其指向新的主库。
-
重新启动复制
所有从库重新开始从新的主库进行复制,恢复正常的复制拓扑结构。
-
通知和日志
MHA Manager 在故障切换完成后,记录日志并通过邮件或其他方式通知管理员。
二、环境
1、服务器环境
MHA manager 最好是单独一台机器部署,尽量不要混部。
系统 | 配置 | IP | 备注 |
---|---|---|---|
- | - | 192.168.56.30 | VIP |
CentOS 7.9 | 2C/2G 20G | 192.168.56.20 | MHA-Manage |
CentOS 7.9 | 2C/2G 20G | 192.168.56.10 | mysql-master,MHA-Node |
CentOS 7.9 | 2C/2G 20G | 192.168.56.11 | mysql-slave1,MHA-Node |
CentOS 7.9 | 2C/2G 20G | 192.168.56.12 | mysql-Slave2,MHA-Node |
2、MySQL 环境
版本 | 备注 |
---|---|
5.7.41 | GTID 的主从复制 |
3、MySQL 主从架构
目前 MHA 主要支持一主多从的架构,要搭建 MHA,要求一个复制集群中必须最少有三台数据库服务器,一主二从,即一台充当master,一台充当备用 master,另外一台充当从库,因为至少需要三台服务器,出于机器成本的考虑,淘宝也在该基础上进行了改造,目前淘宝 TMHA 已经支持一主一从。
本次实验,处了一主二从的三台服务器外,还有额外有一台来作为 MHA Manager,用于管理多个 master-slave 集群,当然,如果你的服务器不富裕,也可以部署在一台 slave 节点上,MHA 功能:主库失效 、备选主库成为主库 、源故障主库恢复重新加入到MHA成为从库。
4、MHA 架构
-
管理一个 MySQL 集群
即 MHA 可管理单个 MySQL 集群。
-
管理多个 MySQL集群
即 MHA 可管理多个 MySQL 集群。
三、部署
3.1 基本环境
3.1.1 hosts 配置
# mha-manager服务器配置
192.168.56.10 mysql-master mha-node1
192.168.56.11 mysql-slave1 mha-node2
192.168.56.12 mysql-slave2 mha-node3
192.168.56.20 mha-manager mha-node4
# mysql-master服务器配置
192.168.56.10 mysql-master mha-node1
192.168.56.11 mysql-slave1 mha-node2
192.168.56.12 mysql-slave2 mha-node3
192.168.56.20 mha-manager mha-node4
# mysql-slave1服务器配置
192.168.56.10 mysql-master mha-node1
192.168.56.11 mysql-slave1 mha-node2
192.168.56.12 mysql-slave2 mha-node3
192.168.56.20 mha-manager mha-node4
# mysql-slave2服务器配置
192.168.56.10 mysql-master mha-node1
192.168.56.11 mysql-slave1 mha-node2
192.168.56.12 mysql-slave2 mha-node3
192.168.56.20 mha-manager mha-node4
3.1.2 配置 SSH 免密访问
免密的目的:在 Master 故障时,MHA-Manage 才能 SSH 连接进去,实现主备切换。
1、MHA manager 节点上生成密钥
ssh-keygen
2、将密钥分发至 MySQL 集群节点
# mha-manager服务器上执行 - 主机名形式
ssh-copy-id mysql-master # 分发给mysql-master
ssh-copy-id mysql-slave1 # 分发给mysql-slave1
ssh-copy-id mysql-slave2 # 分发给mysql-slave2
# mha-manager服务器上执行 - IP形式
ssh-copy-id 192.168.56.10 # 分发给mysql-master
ssh-copy-id 192.168.56.11 # 分发给mysql-slave1
ssh-copy-id 192.168.56.12 # 分发给mysql-slave2
3、MySQL 集群节点间 SSH 互做免密,否则将会报如下错
因为 MySQL 节点间也要进行 SSH 通信。
# 生成密钥(在mysql-master、mysql-slave1、mysql-slave2执行)
ssh-keygen
# 分发密钥(mysql集群间互相分发)- 主机名形式
# [mysql-master节点执行分发]
ssh-copy-id mysql-slave1
ssh-copy-id mysql-slave2
# [mysql-slave1节点执行分发]
ssh-copy-id mysql-master
ssh-copy-id mysql-slave2
# [mysql-slave2节点执行分发]
ssh-copy-id mysql-master
ssh-copy-id mysql-slave1
# 分发密钥(mysql集群间互相分发)- IP形式
# [mysql-master节点执行分发]
ssh-copy-id 192.168.56.11
ssh-copy-id 192.168.56.12
# [mysql-slave1节点执行分发]
ssh-copy-id 192.168.56.10
ssh-copy-id 192.168.56.12
# [mysql-slave2节点执行分发]
ssh-copy-id 192.168.56.10
ssh-copy-id 192.168.56.11
3.2 MySQL 主从
本次使用 GTID 的方式配置主从。
从 MHA 0.56 开始,MHA 支持基于 GTID 的故障转移和传统的基于中继日志的故障转移。 MHA 自动区分选择哪个故障转移。要执行基于 GTID 的故障转移,需要满足以下所有条件:
使用 MySQL 5.6(或更高版本)
所有 MySQL 实例都使用 gtid_mode=1
至少其中一个实例启用了 Auto_Position
在 MySQL 5.6 及更高版本中,启用 GTID 模式后,自动位置分配会自动生效(无需配置)。
路径规范问题:
- MySQL 集群中路径尽量保持一致,尤其是 Binlog 日志路径(因为 MHA 配置文件中会指定)
- 数据路径:/data/mysql_install/data
- 配置路径:/data/mysql_install/conf
- 日志路径:/data/mysql_install/logs
3.2.1 基础环境配置
56.10 主机
1、修改主机名
hostnamectl set-hostname mysql-master
2、Docker 环境部署
Docker version 23.0.6, build ef23cbc
3、创建数据持久化目录
mkdir -p /data/mysql_install/{data,logs,conf}
4、data/logs 目录授权
chmod -R 777 /data/mysql_install/{data,logs}
5、准备 MySQL 配置文件
# 看附件
/data/mysql_install/conf/my.cnf
56.11 主机
1、修改主机名
hostnamectl set-hostname mysql-slave1
2、Docker 环境部署
同上!
3、创建数据持久化目录
同上!
4、data/logs 目录授权
同上!
5、准备 MySQL 配置文件
看附件!
56.12 主机
1、修改主机名
hostnamectl set-hostname mysql-slave2
2、Docker 环境部署
同上!
3、创建数据持久化目录
同上!
4、data/logs 目录授权
同上!
5、准备 MySQL 配置文件
看附件!
3.2.2 启动 MySQL 实例
1、mysql-master
vim /data/mysql_install/docker-compose.yml
version: '3'
services:
mysql-master-service:
image: mysql:5.7.41
container_name: mysql-master
restart: always
network_mode: "host"
environment:
- MYSQL_ROOT_PASSWORD=Zhurs@123!
- TZ=Asia/Shanghai
volumes:
- /data/mysql_install/conf:/etc/mysql/conf.d
- /data/mysql_install/logs:/var/log/mysql
- /data/mysql_install/data:/var/lib/mysql
cd /data/mysql_install/ && docker compose up -d
2、mysql-slave1
vim /data/mysql_install/docker-compose.yml
version: '3'
services:
mysql-slave1-service:
image: mysql:5.7.41
container_name: mysql-slave1
restart: always
network_mode: "host"
environment:
- MYSQL_ROOT_PASSWORD=Zhurs@123!
- TZ=Asia/Shanghai
volumes:
- /data/mysql_install/conf:/etc/mysql/conf.d
- /data/mysql_install/logs:/var/log/mysql
- /data/mysql_install/data:/var/lib/mysql
cd /data/mysql_install/ && docker compose up -d
3、mysql-slave2
vim /data/mysql_install/docker-compose.yml
version: '3'
services:
mysql-slave2-service:
image: mysql:5.7.41
container_name: mysql-slave2
restart: always
network_mode: "host"
environment:
- MYSQL_ROOT_PASSWORD=Zhurs@123!
- TZ=Asia/Shanghai
volumes:
- /data/mysql_install/conf:/etc/mysql/conf.d
- /data/mysql_install/logs:/var/log/mysql
- /data/mysql_install/data:/var/lib/mysql
cd /data/mysql_install/ && docker compose up -d
3.2.3 配置 MySQL 主从
1、mysql-master 创建主从同步账号
docker exec mysql-master mysql -u root -p'Zhurs@123!' -e "create user 'repl_master'@'%' identified by 'zhurs@123.com';grant replication slave,reload,super on *.* to 'repl_master'@'%' with grant option;flush privileges;"
2、mysql-slave1 同步 mysql-master
docker exec mysql-slave1 mysql -u root -p'Zhurs@123!' -e "CHANGE MASTER TO master_host='192.168.56.10', master_port=3306, master_user='repl_master', master_password='zhurs@123.com', master_auto_position=1;start slave;"
查看主从状态:
docker exec mysql-slave1 mysql -u root -p'Zhurs@123!' -e "show slave status\G"
3、mysql-slave2 同步 mysql-master
docker exec mysql-slave2 mysql -u root -p'Zhurs@123!' -e "CHANGE MASTER TO master_host='192.168.56.10', master_port=3306, master_user='repl_master', master_password='zhurs@123.com', master_auto_position=1;start slave;"
查看主从状态:
docker exec mysql-slave2 mysql -u root -p'Zhurs@123!' -e "show slave status\G"
3.2.4 MySQL 主从同步验证
在 mysql-master 上创建一个测试数据库,看 mysql-slave1、mysql-slave2 是否同步。
mysql-master:
docker exec mysql-master mysql -u root -p'Zhurs@123!' -e "create database tmptest;"
mysql-slave1 验证:
docker exec mysql-slave1 mysql -u root -p'Zhurs@123!' -e "show databases;"
mysql-slave2 验证:
docker exec mysql-slave2 mysql -u root -p'Zhurs@123!' -e "show databases;"
至此,主从同步配置完成!
3.3 MHA 部署
参考文档:https://www.cnblogs.com/liugp/p/16500022.html
参考文档:https://www.cnblogs.com/sunnytomorrow/p/15794946.html
3.3.1 MHA node
所有节点都需要安装 MHA node(即 56.10、56.11、56.12、56.20 节点都要部署)
1、安装相关依赖
yum install perl-DBD-MySQL -y
2、MHA node 安装
rpm 包下载地址:https://github.com/yoshinorim/mha4mysql-node/releases
# 下载
wget https://github.com/yoshinorim/mha4mysql-node/releases/download/v0.58/mha4mysql-node-0.58-0.el7.centos.noarch.rpm
# 安装
rpm -ivh mha4mysql-node-0.58-0.el7.centos.noarch.rpm
3.3.2 MHA manager
MHA manager 节点部署(即 56.20 节点部署)
1、安装相关依赖
yum -y install epel-release
yum -y install perl-Config-Tiny perl-Time-HiRes perl-Parallel-ForkManager perl-Log-Dispatch perl-DBD-MySQL ncftp
2、MHA manager 安装
rpm 包下载地址:https://github.com/yoshinorim/mha4mysql-manager/releases/
# 下载
wget https://github.com/yoshinorim/mha4mysql-manager/releases/download/v0.58/mha4mysql-manager-0.58-0.el7.centos.noarch.rpm
# 安装
rpm -ivh mha4mysql-manager-0.58-0.el7.centos.noarch.rpm
3.4 MHA 配置
3.4.1 为 MHA 创建一个帐户
在 mysql-master 主节点上执行,执行后 mha 账户会同步到 slave 上。
docker exec mysql-master mysql -u root -p'Zhurs@123!' -e "CREATE USER mha@'%' IDENTIFIED BY 'Security0527';"
docker exec mysql-master mysql -u root -p'Zhurs@123!' -e "GRANT ALL PRIVILEGES ON *.* TO mha@'%';"
docker exec mysql-master mysql -u root -p'Zhurs@123!' -e "FLUSH PRIVILEGES;"
3.4.2 mha-manager 创建配置文件
在 mha-manager 上创建配置文件目录并创建配置 app1.cnf
1、创建 MHA 相关目录
# 在mha-manager上创建相关工作目录
mkdir -p /data/masterha/{conf,logs,scripts}
# 在所有mha-node上创建相关工作目录
mkdir -p /data/nodeha
2、在 mha-manager 上创建配置文件
vim /data/masterha/conf/mysql_mha.cnf
[server default]
# 指定mha-manager访问MySQL数据库信息
user=mha
password=Security0527
port=3306
# 指定 MHA-manage 的工作目录
manager_workdir=/data/masterha
# 指定 MHA-node 工作目录(即 mha 在远程 mha-node 节点的工作目录)
remote_workdir=/data/nodeha
# 指定 MHA-manage 的日志路径
manager_log=/data/masterha/logs/manager.log
# 指定存放 MySQL master 的 binlog 的日志文件所在目录
master_binlog_dir=/data/mysql_install/data
# 指定主从复制的 mysq 用户和密码
repl_user=repl_master
repl_password=zhurs@123.com
# SSH 连接用户(我们已经做了免密)
ssh_user=root
# 指定检测间隔时间
ping_interval=1
# 指定一个脚本,该脚本实现了在主从切换之后,将虚拟ip漂移到新的master上
master_ip_failover_script=/data/masterha/scripts/master_ip_failover
# 指定检查的从服务器IP地址的脚本,有几个,就用-s选项加几个(这个脚本可手动修改,比如ssh用户名/MySQL端口等,根据实际修改)
secondary_check_script=/usr/bin/masterha_secondary_check -s mysql-master -s mysql-slave1 -s mysql-slave2
# 用于故障切换的时候发送邮件提醒(先暂时不用)
#report_script=/data1/mysql-mha/send_mail
# mysql 集群节点
# mysql-master
[server1]
hostname=mysql-master
port=3306
ssh_user=root
ssh_port=22
candidate_master=1
check_repl_delay=0
# mysql-slave1
[server2]
hostname=mysql-slave1
port=3306
ssh_user=root
ssh_port=22
candidate_master=1
check_repl_delay=0
# mysql-slave2
[server3]
hostname=mysql-slave2
port=3306
ssh_user=root
ssh_port=22
candidate_master=1
check_repl_delay=0
参数说明:
candidate_master=1
参数用于标识候选主库。候选主库是指在当前主库发生故障时,可以被提升为新主库的从库节点。配置此参数可以帮助 MHA 在进行主库故障转移时,优先选择合适的候选主库进行切换。
check_repl_delay=0
该参数用于控制在主库故障转移时是否检查从库的复制延迟。
0
表示不检查从库的复制延迟。
1
表示检查从库的复制延迟,默认值,如果复制延迟较大,从库不会被选为新的主库。使用场景:
- check_repl_delay=0 在非常紧急的情况下,你需要尽快恢复业务,而不考虑数据延迟问题。这个参数对于设置了candidate_master=1的主机非常有用,因为这个候选主在切换的过程中一定是新的 master。
- check_repl_delay=1 通常情况下,建议保持默认值,以确保提升为新主库的从库数据尽量与原主库保持一致,减少数据不一致的风险。
上面配置文件中有 [server default]、[server1]、[server2]…等字段,这些字段中的参数是一种包含关系。
- 比如你的 [server default] 字段中指定了参数 port=3306
- [server1] 字段也指定了参数 port=13306
- 那此时的 port 值以 [server1] 为准,即 13306,如果没有指定参数,则以 [server default] 中的参数值为准。
3、编写 master_ip_failover 脚本
在 /data/masterha/conf/mysql_mha.cnf 配置中提到的虚拟IP漂移脚本
vim /data/masterha/scripts/master_ip_failover
#!/usr/bin/env perl
use strict;
use warnings FATAL => 'all';
use Getopt::Long;
my (
$command, $orig_master_host, $orig_master_ip,$ssh_user,
$orig_master_port, $new_master_host, $new_master_ip,$new_master_port,
$orig_master_ssh_port,$new_master_ssh_port,$new_master_user,$new_master_password
);
# 这里定义的虚拟IP配置要注意,这个ip必须要与你自己的集群在同一个网段,否则无效
my $vip = '192.168.56.30/24';
my $key = '1';
# 这里的网卡名称 “ens33” 需要根据你机器的网卡名称进行修改
# 如果多台机器直接的网卡名称不统一,有两种方式,一个是改脚本,二是把网卡名称修改成统一
# 我这边实际情况是修改成统一的网卡名称
my $ssh_start_vip = "sudo /sbin/ifconfig ens33:$key $vip";
my $ssh_stop_vip = "sudo /sbin/ifconfig ens33:$key down";
my $ssh_Bcast_arp= "sudo /sbin/arping -I bond0 -c 3 -A $vip";
GetOptions(
'command=s' => \$command,
'ssh_user=s' => \$ssh_user,
'orig_master_host=s' => \$orig_master_host,
'orig_master_ip=s' => \$orig_master_ip,
'orig_master_port=i' => \$orig_master_port,
'orig_master_ssh_port=i' => \$orig_master_ssh_port,
'new_master_host=s' => \$new_master_host,
'new_master_ip=s' => \$new_master_ip,
'new_master_port=i' => \$new_master_port,
'new_master_ssh_port' => \$new_master_ssh_port,
'new_master_user' => \$new_master_user,
'new_master_password' => \$new_master_password
);
exit &main();
sub main {
$ssh_user = defined $ssh_user ? $ssh_user : 'root';
print "\n\nIN SCRIPT TEST====$ssh_user|$ssh_stop_vip==$ssh_user|$ssh_start_vip===\n\n";
if ( $command eq "stop" || $command eq "stopssh" ) {
my $exit_code = 1;
eval {
print "Disabling the VIP on old master: $orig_master_host \n";
&stop_vip();
$exit_code = 0;
};
if ($@) {
warn "Got Error: $@\n";
exit $exit_code;
}
exit $exit_code;
}
elsif ( $command eq "start" ) {
my $exit_code = 10;
eval {
print "Enabling the VIP - $vip on the new master - $new_master_host \n";
&start_vip();
&start_arp();
$exit_code = 0;
};
if ($@) {
warn $@;
exit $exit_code;
}
exit $exit_code;
}
elsif ( $command eq "status" ) {
print "Checking the Status of the script.. OK \n";
exit 0;
}
else {
&usage();
exit 1;
}
}
sub start_vip() {
`ssh $ssh_user\@$new_master_host \" $ssh_start_vip \"`;
}
sub stop_vip() {
`ssh $ssh_user\@$orig_master_host \" $ssh_stop_vip \"`;
}
sub start_arp() {
`ssh $ssh_user\@$new_master_host \" $ssh_Bcast_arp \"`;
}
sub usage {
print
"Usage: master_ip_failover --command=start|stop|stopssh|status --ssh_user=user --orig_master_host=host --orig_master_ip=ip --orig_master_port=port --new_master_host=host --new_master_ip=ip --new_master_port=port\n";
}
赋予可执行权限:
chmod a+x /data/masterha/scripts/master_ip_failover
3.4.3 mysql-slave 中继日志关闭自动清除
重要:在 mysql-slave1、mysql-slave2 上设置从库 relay_log_purge 参数,MHA在发生主从切换的过程中,从库的恢复过程依赖于 relay log,所以这里要将 relay log 的自动清除设置为 OFF,即采用手动清除 relay log 的方式。在默认情况下,从服务器上的中继日志会在SQL线程执行完毕后被自动删除。但是在MHA环境中,这些中继日志在恢复其他从服务器时可能会被用到,因此需要禁用中继日志的自动删除功能。
当然,当你的 mysql-master 宕机下线后,如果要重新成为 MySQL 集群的 slave 节点时,其中继日志 relay_log_purge 参数也应该设置为 OFF。
[mysqld]
relay_log_purge=OFF
设置 relay_log_purge=OFF
后,MySQL 将不会自动清除不再需要的中继日志文件,而是会保留它们直到手动删除或者达到了存储限制。请注意,手动管理中继日志文件可能会增加磁盘空间的使用,并且需要定期检查和清理不再需要的文件。
3.4.4 mysql-master 启用 VIP
# 在当前的mysql-master上配置
# 标签要和master_ip_faioverl配置文件中my $key = '1'; 一样
ifconfig ens33:1 192.168.56.30/24
3.5 MHA 可用性测试
3.5.1 测试 ssh 免密认证
masterha_check_ssh -conf=/data/masterha/conf/mysql_mha.cnf
SSH 免密认证通过!
3.5.2 测试 mysql 主从状态
masterha_check_repl -conf=/data/masterha/conf/mysql_mha.cnf
MySQL 主从健康认证通过!
3.6 启动 MHA
1、启动
nohup masterha_manager \
--conf=/data/masterha/conf/mysql_mha.cnf \
--remove_dead_master_conf \
--ignore_last_failover < /dev/null > /var/log/mha_manager.log 2>&1 &
2、检查 MHA 状态
masterha_check_status --conf=/data/masterha/conf/mysql_mha.cnf
3、查看 MHA 日志文件
4、如何关闭 MHA ?
masterha_stop --conf=/opt/mysql-mha/mysql_mha.cnf
四、故障模拟与恢复
至此,所有环境都准备完毕,接下来就是模拟故障及恢复了。
4.1 故障
这里模拟 mysql-master 宕机的场景。
1、停止 mysql-master 服务
docker compose down
2、此时 VIP 从 mysql-master 漂移到 mysql-slave1 了
3、我们去 mysql-slave2 验证一下 mysql-slave1 是否为 master 节点
docker exec mysql-slave2 mysql -u root -p'Zhurs@123!' -e "show slave status\G"
可看到 mysql-slave2 上可看到,此时他的 master 节点为 mysql-slave1,证明故障自动转移。
4、这个时候我在 mysql-slave1 上创建一个测试数据库
docker exec mysql-slave1 mysql -u root -p'Zhurs@123!' -e "create database hello_mha;"
5、看看 mysql-slave2 是否正常同步
docker exec mysql-slave2 mysql -u root -p'Zhurs@123!' -e "show databases;"
没问题,正常同步!
4.2 恢复
此时,我启动 mysql-master 实例,并进行主从配置,看又是否能同步 mysql-slave1 的数据。
1、启动 mysql-master 实例
docker compose up -d
docker ps
2、配置主从同步
docker exec mysql-master mysql -u root -p'Zhurs@123!' -e "CHANGE MASTER TO master_host='192.168.56.11', master_port=3306, master_user='repl_master', master_password='zhurs@123.com', master_auto_position=1;start slave;"
3、查看主从状态
docker exec mysql-master mysql -u root -p'Zhurs@123!' -e "show slave status\G"
4、验证 mysql-master 数据完整性
看看是否进行了数据同步
docker exec mysql-master mysql -u root -p'Zhurs@123!' -e "show databases;"
没问题,主从数据正常同步。
五、应用程序如何连接?
在 MHA 的配置处,我们指定了虚拟 IP(VIP),其实这就是我们应用程序的连接地址,因为 VIP 总是跟随主节点的移动而移动,即 VIP 所在节点就是 master 节点,且实际生产中,我们应用程序的写肯定是 master 节点,至于读当然也可以是 master,同时也支持对 slave 节点的只读,可做读写分离。
验证一下通过 VIP 是否能正常连接数据库,如下图,可正常连接:
看看是否有数据:
至此,基于 MHA 的 MySQL 高可用主从架构部署结束。
总结
通过以上的点滴部署,实际上你会发现,在 MHA 的世界其实没有主从,都是平等的 MySQL 节点,因为这些节点可能会根据恶劣的环境随时跟换主节点,因此,我们在设计这种 MySQL 主从架构时,应保持 MySQL 集群节点的规格/配置一致,这样就不会因为发生主从切换时,数据的写入即复制延迟,导致对外提供服务发生异常(尤其是生产环境下)。
MHA 不足之处在于它只保证了 master 的高可用,并没有监控 slave 的状态,如果某 slave 出现复制中断、延迟增加等问题,都是不知道的。同时,MHA Manager 本身可能成为单点故障,因此需要进行高可用配置,如通过 Heartbeat 或 Pacemake r等高可用软件进行保护。
附件
my.cnf
注意:master、slave1 和 slave2 的 server-id 要唯一,所以下面的这个配置文件分发给 MySQL Slave 时注意 server-id 唯一性问题
[client]
port = 3306
[mysqld]
#innodb_force_recovery = 6 # 数据恢复参数,在数据表结构异常时使用(缺省值为0)
port = 3306
pid-file = /var/run/mysqld/mysqld.pid
socket = /var/run/mysqld/mysqld.sock
datadir = /var/lib/mysql
log-error = /var/log/mysql/error.log
# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0
max_connections = 2000
max_user_connections = 1900
max_connect_errors = 100000
max_allowed_packet = 50M
lower_case_table_names=1
# datetime
default-time_zone = 'Asia/Shanghai'
log_timestamps = SYSTEM
# GTID
server-id=2
gtid_mode = ON
enforce_gtid_consistency=1
master-info-repository=TABLE
relay-log-info-repository=TABLE
relay_log_purge=OFF
# Binlog
log-bin = mysql-binlog
# relay-log
relay-log=relay-bin
[mysqld]
skip-name-resolve
sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
—END