一、MySQL高可用方案
什么是高可用?高可用其实就是可以实现自动故障转移。当主节点挂了之后其他节点可以自动顶上,防止节点出现故障时MySQL不能对外提供服务。
MySQL的高可用解决方案其实有很多种(想了解自行百度),这里只说其中一种:MHA。这也是当前比较主流的方案。
二、MHA详解
-
什么是MHA?
MHA 是 Master High Availability 的缩写,直译过来就是“主机高可用”。它是一款当前主流的相对成熟的MySQL高可用方案之一,能做到在0~30s内自动完成MySQL的故障切换操作,在master服务器不宕机的情况下,基本能保证数据的一致性。
-
MHA的组成
MHA由两部分组成,MHA Manager 和 MHA Node
-
MHA Manager(管理节点)
MHA Manager可以单独部署在一台独立的机器上管理多个master-slave集群,也可以部署在master-slave集群中任意一台机器上,建议单独部署在一台独立的机器上。
-
MHA Node(数据节点)
MHA Node运行在每台MySQL服务器上,是MHA Manager的员工,接收Manager的命令并执行
-
-
MHA的工作原理
- 从宕机崩溃的master保存二进制日志事件(binlog events)
- 识别含有最新更新的slave
- 应用差异的中继日志(relay log)到其他的slave
- 应用从master保存的二进制日志事件(binlog events)
- 提升一个slave为新的master
- 使其他的slave连接新的master进行主从复制
-
MHA各个工具包的作用
manager工具包:
组件名称 组件说明 masterha_check_ssh 检查MHA的SSH配置状况 masterha_check_repl 检查MySQL复制状况 masterha_manger 启动MHA masterha_check_status 检测当前MHA运行状态 masterha_master_monitor 检测master是否宕机 masterha_master_switch 控制故障转移(自动或者手动) masterha_conf_host 添加或删除配置的server信息 node工具包:
组件名称 组件说明 save_binary_logs 保存和复制master的二进制日志 apply_diff_relay_logs 识别差异的中继日志事件并将其差异的事件应用于其他的slave filter_mysqlbinlog 去除不必要的ROLLBACK事件(MHA已不再使用这个工具) purge_relay_logs 清除中继日志(不会阻塞SQL线程) -
manager和node的工具包可以通过我的网盘下载安装包
链接:https://pan.baidu.com/s/1WQHUrFVBpafLveNfXxaPUg 提取码:3w31
三、搭建MHA
在搭建MHA之前应该先保证已经安装配置好了MySQL的主从/集群。因为既然是高可用架构,那么针对的肯定是多台设备,单机的话谈不上高可用。
MySQL的主从搭建过程这里就不说了,可以看这里:MySQL搭建主从架构
本次搭建环境:centos7.8 + mysql5.7.31
角色 | IP地址 | 以下简称 | server_id |
---|---|---|---|
MHA Manager | 192.168.241.104 | 104 | - |
mysql master | 192.168.241.101 | 101 | 101 |
mysql slave1 | 192.168.241.102 | 102 | 102 |
mysql slave2 | 192.168.241.103 | 103 | 103 |
-
秘钥互信
因为MHA在故障转移时要移动binlog日志和中继日志,需要在节点进行ssh通信,所以要设置下秘钥互信,也就是需要配置下免密登录。
在所有的机器上执行以下命令
cd ~ ssh-keygen -t rsa #一路回车 cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys chmod 600 ~/.ssh/authorized_keys
在104机器上执行以下命令
ssh 192.168.241.101 cat ~/.ssh/id_rsa.pub >>~/.ssh/authorized_keys ssh 192.168.241.102 cat ~/.ssh/id_rsa.pub >>~/.ssh/authorized_keys ssh 192.168.241.103 cat ~/.ssh/id_rsa.pub >>~/.ssh/authorized_keys scp ~/.ssh/authorized_keys 192.168.241.101:~/.ssh/ scp ~/.ssh/authorized_keys 192.168.241.102:~/.ssh/ scp ~/.ssh/authorized_keys 192.168.241.103:~/.ssh/
执行完成后需要在每台机器上测试一遍,看是否配置成功。执行
ssh root@192.168.241.101(其他机器的IP)
,如果可以直接登录,输入ip a
发现IP确实变成了登录的那台,证明互信建立成功。[root@bogon ~]# ip a | grep 104 inet 192.168.241.104/24 brd 192.168.241.255 scope global noprefixroute ens32 [root@bogon ~]# [root@bogon ~]# ssh root@192.168.241.101 Last login: Sun Jun 27 22:10:37 2021 from 192.168.241.101 [root@bogon ~]# ip a | grep 101 inet 192.168.241.101/24 brd 192.168.241.255 scope global noprefixroute ens32 [root@bogon ~]#
-
在所有机器上安装依赖
yum install -y perl-ExtUtils-CBuilder perl-ExtUtils-MakeMaker perl-CPAN perl-DBD-MySQL perl-Config-Tiny perl-Log-Dispatch perl-Parallel-ForkManager perl-Time-HiRes
-
安装 MHA Node组件
在所有机器上安装node工具包
cd /usr/local/src/ mkdir mha && cd mha # 将mha4mysql-node-0.58.tar.gz压缩包上传到这 tar -zxvf mha4mysql-node-0.58.tar.gz cd mha4mysql-node-0.58 # 校验 perl Makefile.PL make && make install
安装完成后会得到四个工具,位于/usr/local/bin/下面
[root@bogon mha4mysql-node-0.58]# cd /usr/local/bin/ [root@bogon bin]# ll | grep log -r-xr-xr-x 1 root root 17639 6月 27 22:57 apply_diff_relay_logs -r-xr-xr-x 1 root root 4807 6月 27 22:57 filter_mysqlbinlog -r-xr-xr-x 1 root root 8337 6月 27 22:57 purge_relay_logs -r-xr-xr-x 1 root root 7525 6月 27 22:57 save_binary_logs [root@bogon bin]#
-
安装 MHA Manager 组件
manager工具包只需要安装在一台机器上,可以是单独的服务器,也可以是集群中任一节点,这里安装在单独的104机器上,安装过程与node工具包一致
# 将mha4mysql-manager-0.58.tar.gz压缩包上传到这 tar -zxvf mha4mysql-manager-0.58.tar.gz cd mha4mysql-manager-0.58 perl Makefile.PL make && make install
安装完成后在 /usr/local/bin/ 下面可以看到相关的工具
[root@bogon mha4mysql-manager-0.58]# cd /usr/local/bin/ [root@bogon bin]# ll | grep master -r-xr-xr-x 1 root root 1995 6月 27 23:14 masterha_check_repl -r-xr-xr-x 1 root root 1779 6月 27 23:14 masterha_check_ssh -r-xr-xr-x 1 root root 1865 6月 27 23:14 masterha_check_status -r-xr-xr-x 1 root root 3201 6月 27 23:14 masterha_conf_host -r-xr-xr-x 1 root root 2517 6月 27 23:14 masterha_manager -r-xr-xr-x 1 root root 2165 6月 27 23:14 masterha_master_monitor -r-xr-xr-x 1 root root 2373 6月 27 23:14 masterha_master_switch -r-xr-xr-x 1 root root 5172 6月 27 23:14 masterha_secondary_check -r-xr-xr-x 1 root root 1739 6月 27 23:14 masterha_stop [root@bogon bin]#
-
MHA Manage 机器上需要做的一些配置
# 创建MHA配置文件目录 mkdir /etc/mha # 创建MHA脚本目录 mkdir /etc/mha/scripts # 创建MHA日志目录 mkdir /var/log/mha/ # 创建日志目录(app1是自定义的,因为manager可以同时管理多个集群,所以这里取了这个名) mkdir -p /var/log/mha/app1 # 创建日志文件 touch /var/log/mha/app1/manager.log
创建第一个配置文件,这个配置主要是一个mysql主从的名单。 candidate_master=1的意思是是否能提升为master,可以不加。
vi /etc/mha/app1.cnf # 加入这些内容 [server default] manager_workdir=/var/log/mha/app1 manager_log=/var/log/mha/app1/manager.log [server1] hostname=192.168.241.101 port=3306 [server2] hostname=192.168.241.102 port=3306 candidate_master=1 [server3] hostname=192.168.241.103 port=3306
创建第二个配置文件
vi /etc/masterha_default.cnf # 加入这些内容 [server default] user=repl password=123456 repl_user=repl repl_password=123456 ssh_user=root ping_interval=1 master_binlog_dir=/www/server/data/ manager_workdir=/var/log/mha/app1 manager_log=/var/log/mha/app1/manager.log master_ip_failover_script="/etc/mha/scripts/master_ip_failover" master_ip_online_change_script="/etc/mha/scripts/master_ip_online_change" report_script="/etc/mha/scripts/send_report" remote_workdir=/tmp secondary_check_script= /usr/local/bin/masterha_secondary_check -s 192.168.241.101 -s 192.168.241.102 -s 192.168.241.103 shutdown_script=""
配置参数详解
user=repl:设置监控mysql的用户
password=123456:设置监控mysql的用户密码,需要授权能够在manager节点远程登录
repl_user=repl:设置mysql中用于复制的用户
repl_password=123456:设置mysql中用于复制的用户密码
ssh_user=root:设置ssh的登录用户名
ping_interval=1:设置监控主库,发送ping包的时间间隔,默认是3秒,尝试三次没有回应的时候自动进行railover
master_binlog_dir=/www/server/data/:设置master 保存binlog的位置,以便MHA可以找到master的日志
manager_workdir=/var/log/mha/app1:设置manager的工作目录
manager_log=/var/log/mha/app1/manager.log:设置manager的日志文件
master_ip_failover_script="/etc/mha/scripts/master_ip_failover":设置自动failover时候的切换脚本 master_ip_online_change_script="/etc/mha/scripts/master_ip_online_change":设置手动切换时候的切换脚本
report_script=/usr/local/send_report:设置发生切换后发送的报警的脚本
remote_workdir=/tmp:设置远端mysql在发生切换时binlog的保存位置
shutdown_script="":设置故障发生后关闭故障主机脚本(该脚本的主要作用是关闭主机防止发生脑裂,这里没有使用)
candidate_master=1:在从节点下设置,设置当前节点为候选的master
slave check_repl_delay=0 :在节点配置下设置,默认情况下如果一个slave落后master 100M的relay logs的话,MHA将不会选择该slave作为一个新 的master;这个选项对于对于设置了candidate_master=1的主机非常有用
脚本配置
vi /etc/mha/scripts/master_ip_failover
#!/usr/bin/env perl use strict; use warnings FATAL => 'all'; use Getopt::Long; my ( $command, $ssh_user, $orig_master_host, $orig_master_ip, $orig_master_port, $new_master_host, $new_master_ip, $new_master_port ); my $vip = '192.168.241.105'; my $key = '0'; my $ssh_start_vip = "ifconfig ens32:0 192.168.241.105 netmask 255.255.255.0 up"; my $ssh_stop_vip = "/sbin/ifconfig ens32:$key down"; 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, 'new_master_host=s' => \$new_master_host, 'new_master_ip=s' => \$new_master_ip, 'new_master_port=i' => \$new_master_port, ); exit &main(); sub main { print "\n\nIN SCRIPT TEST====$ssh_stop_vip==$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(); $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() { return 0 unless ($ssh_user); `ssh $ssh_user\@$orig_master_host \" $ssh_stop_vip \"`; } sub usage { print "Usage: master_ip_failover --command=start|stop|stopssh|status --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"; }
注意:这里的变量 key 要换成自己的;如果网卡类型不是ens32的,也要把文中的ens32换成自己的
最后给这个脚本增加执行权限
chmod +x /etc/mha/scripts/master_ip_failover
-
通过 masterha_check_ssh 命令验证ssh 信任登录是否成功
[root@bogon bin]# masterha_check_ssh --conf=/etc/mha/app1.cnf Sat Jul 3 01:22:18 2021 - [info] Reading default configuration from /etc/masterha_default.cnf.. Sat Jul 3 01:22:18 2021 - [info] Reading application default configuration from /etc/mha/app1.cnf.. Sat Jul 3 01:22:18 2021 - [info] Reading server configuration from /etc/mha/app1.cnf.. Sat Jul 3 01:22:18 2021 - [info] Starting SSH connection tests.. Sat Jul 3 01:22:19 2021 - [debug] Sat Jul 3 01:22:18 2021 - [debug] Connecting via SSH from root@192.168.241.101(192.168.241.101:22) to root@192.168.241.102(192.168.241.102:22).. Sat Jul 3 01:22:19 2021 - [debug] ok. Sat Jul 3 01:22:19 2021 - [debug] Connecting via SSH from root@192.168.241.101(192.168.241.101:22) to root@192.168.241.103(192.168.241.103:22).. Sat Jul 3 01:22:19 2021 - [debug] ok. Sat Jul 3 01:22:20 2021 - [debug] Sat Jul 3 01:22:19 2021 - [debug] Connecting via SSH from root@192.168.241.102(192.168.241.102:22) to root@192.168.241.101(192.168.241.101:22).. Sat Jul 3 01:22:19 2021 - [debug] ok. Sat Jul 3 01:22:19 2021 - [debug] Connecting via SSH from root@192.168.241.102(192.168.241.102:22) to root@192.168.241.103(192.168.241.103:22).. Warning: Permanently added '192.168.241.103' (ECDSA) to the list of known hosts. Sat Jul 3 01:22:20 2021 - [debug] ok. Sat Jul 3 01:22:21 2021 - [debug] Sat Jul 3 01:22:19 2021 - [debug] Connecting via SSH from root@192.168.241.103(192.168.241.103:22) to root@192.168.241.101(192.168.241.101:22).. Sat Jul 3 01:22:20 2021 - [debug] ok. Sat Jul 3 01:22:20 2021 - [debug] Connecting via SSH from root@192.168.241.103(192.168.241.103:22) to root@192.168.241.102(192.168.241.102:22).. Warning: Permanently added '192.168.241.102' (ECDSA) to the list of known hosts. Sat Jul 3 01:22:20 2021 - [debug] ok. Sat Jul 3 01:22:21 2021 - [info] All SSH connection tests passed successfully. [root@localhost bin]#
显示这样,表示成功
-
通过 masterha_check_repl 命令验证 MySQL主从复制是否成功
这里出现的问题可能有很多,有各种各样的坑,我这里只遇到了下边这一个。如果遇到不同的错误直接百度,网上有很多讲报错的文章
1、错误信息:Can't exec "mysqlbinlog": 没有那个文件或目录 at /usr/local/share/perl5/MHA/BinlogManager.pm line 106.
2、解决方案:在三台MySQL机器上添加mysqlbinlog软链接(mysqlbinlog的路径根据自己实际的来)
ln -s /www/server/mysql/bin/mysqlbinlog /usr/local/bin/mysqlbinlog
当最后出现这个提示,则表示成功
MySQL Replication Health is OK.
-
启动 MHA
初次使用的时候,需要先在master节点上添加vip,以后就不需要了
ifconfig ens32:0 192.168.232.105 netmask 255.255.255.0 up
在104机器上执行启动manager
masterha_manager --conf=/etc/mha/app1.cnf --remove_dead_master_conf --ignore_last_failover < /dev/null > /var/log/mha/app1/manager.log
检查 MHA 状态
masterha_check_status --conf=/etc/mha/app1.cnf
关闭 MHA
masterha_stop --conf=/etc/mha/app1.cnf
启动成功后就可以进行模拟宕机测试了
四、模拟宕机测试
现在的架构是 :
101:主节点
102:从节点1
103:从节点2
手动将101的MySQL主节点关闭,在102的节点上查看VIP,发现配置的VIP:192.168.232.105已经从101节点漂移到102节点了。
[root@localhost mha4mysql-node-0.58]# ip a | grep 241
inet 192.168.241.102/24 brd 192.168.241.255 scope global noprefixroute ens32
inet 192.168.241.105/24 brd 192.168.241.255 scope global secondary ens32:0
[root@localhost mha4mysql-node-0.58]#
然后在103的节点上可以看到主节点确实已经变成了 102
mysql> show slave status \G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.241.102
Master_User: repl
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000012
Read_Master_Log_Pos: 154
......
到此,MHA 搭建大功告成啦!
五、总结
MHA 的切换过程,共包括以下的步骤:
- 配置文件检查阶段,这个阶段会检查整个集群配置文件配置
- 宕机的 master 处理,这个阶段包括虚拟 ip 摘除操作,主机关机操作(由于没有定义power_manager脚本,不会关机)
- 复制 dead maste 和最新 slave 相差的 relay log,并保存到 MHA Manger 具体的目录下
- 识别含有最新更新的 slave
- 应用从 master 保存的二进制日志事件(binlog events)(这点信息对于将故障master修复后加入集群很重要)
- 提升一个 slave 为新的 master 进行复制
- 使其他的 slave 连接新的 master 进行复制
最后说明一点,宕机的节点,重启后由于MySQL机制问题不会自动加入到集群中,需要我们手动加入。