有的时候博客内容会有变动,首发博客是最新的,其他博客地址可能会未同步, 认准 https://blog.zysicyj.top
原文地址
MHA 架构介绍 -
MHA 是 Master High Availability 的缩写,它是目前 MySQL 高可用方面的一个相对成熟的解决方案,其核心是使用 perl 语言编写的一组脚本,是一套优秀的作为 MySQL 高可用性环境下故障切换和主从提升的高可用软件。在 MySQL 故障切换过程中,MHA 能做到在 0~ 30 秒之内自动完成数据库的故障切换操作,并且能在最大程度上保证数据的一致性,以达到真正意义上的高可用。
基于 MHA 的架构不像 MMM 那样需要搭建主主复制,只需要搭建基本的主从复制架构即可。因为 MHA 在主库挂掉时,是在多个从库中选取出一个从库作为新的主库。MHA 集群中的各节点彼此之间均需要基于 ssh
互信通信,以实现远程控制及数据管理功能。
MHA 提供了什么功能:
可以监控 Master 节点是否可用
当 Master 不可用时,能在多个 Slave 中选举出新的 Master
提供了主从切换和故障转移功能,MHA 会尝试在宕机的 Master 上保存 binlog,在最大程度上保证事务不丢失。但如果是 Master 所在的服务器已经无法访问,或硬件层面出现了问题,则无法成功保存 binlog
MHA 可以与半同步复制结合,避免从库之间出现数据不一致的情况
支持 MySQL 基于 GTID 和基于日志点的两种复制方式
MHA 故障转移过程:
尝试使用 ssh
登录到宕机崩溃的 Master 节点上保存二进制日志事件(binlog events);
从多个 Slave 中识别含有最新更新的 Slave,将其作为备选的 Master;
然后基于该 Slave 同步差异的中继日志(relaylog)到其他的 Slave 上;
接着同步从原 Master 上保存的二进制日志事件(binlog events);
将备选的 Master 提升为新的 Master;
使其他的 Slave 连接新的 Master 进行复制;
在新的 Master 启动 vip 地址,保证前端请求可以发送到新的 Master。
MHA 的架构图如下:
动手搭建 MHA 架构
本文中所使用的机器说明:
| 名称 | IP | 角色 |
|
—-|
—–
master
slave-01
slave-02
manager
|
环境版本说明:
操作系统版本:CentOS 7
MySQL 版本:8.0.19
MHA 版本:0.58
另外的说明:
会来了解 MMM 架构的小伙伴们想必都已经掌握了 MySQL 的安装方式,而且介绍 MySQL 的安装 也有很多文章,所以本文为了减少不必要的篇幅就不演示 MySQL 的安装了,文中所用到的机器都已经提前安装好了 MySQL。
配置主从节点的配置文件 1、在所有主从节点上使用如下语句创建用于主从复制的 MySQL 用户,因为每个从库都有可能会被选举为主库,所以都需要拥有用于复制的用户:
1 2 3 create user 'repl'@'%' identified with mysql_native_password by 'Abc_123456'; grant replication slave on *.* to 'repl'@'%'; flush privileges;
2、然后修改 master
节点上的 MySQL 配置文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 [root@master ~]# vim /etc/my.cnf [mysqld] # 设置当前节点的 id server_id=101 # 开启 binlog,并指定 binlog 文件的名称 log_bin=mysql_bin # 开启 relay_log,并指定 relay_log 文件的名称 relay_log=relay_bin # 将 relaylog 的同步内容记录到 binlog 中 log_slave_updates=on # 开启 GTID 复制模式 gtid_mode=ON enforce_gtid_consistency=1
3、在 slave-01
的配置文件中也是添加一样配置,只不过 server_id
不一样:
1 2 3 4 5 6 7 8 [root@slave-01 ~]# vim /etc/my.cnf [mysqld] server_id=102 log_bin=mysql_bin relay_log=relay_bin log_slave_updates=on gtid_mode=ON enforce_gtid_consistency=1
4、接着是配置 slave-02
:
1 2 3 4 5 6 7 8 [root@slave-02 ~]# vim /etc/my.cnf [mysqld] server_id=103 log_bin=mysql_bin relay_log=relay_bin log_slave_updates=on gtid_mode=ON enforce_gtid_consistency=1
完成以上配置文件的修改后,分别重启这三个节点上的 MySQL 服务:
1 2 3 [root@master ~]# systemctl restart mysqld [root@slave-01 ~]# systemctl restart mysqld [root@slave-02 ~]# systemctl restart mysqld
配置 slave-01
对 master
的主从关系 1 2 3 mysql> stop slave; -- 停止主从同步 mysql> change master to master_host='192.168.190.151' , master_port=3306, master_user='repl' , master_password='Abc_123456' , master_auto_position=1; -- 配置 master 节点的连接信息 mysql> start slave; -- 启动主从同
进入 slave-01
节点的 MySQL 命令行终端,分别执行如下语句来配置主从复制链路:
配置完主从复制链路后,使用 show slave status\G;
语句查看主从同步状态,Slave_IO_Running
和 Slave_SQL_Running
的值均为 Yes
才能表示主从同步状态是正常的:
配置 slave-02
对 master
的主从关系 1 2 3 mysql> stop slave; -- 停止主从同步 mysql> change master to master_host='192.168.190.151' , master_port=3306, master_user='repl' , master_password='Abc_123456' , master_auto_position=1; -- 配置 master 节点的连接信息 mysql> start slave; -- 启动主从同步
同样的步骤,进入 slave-02
节点的 MySQL 命令行终端,分别执行如下语句来配置主从复制链路:
配置完主从复制链路后,使用 show slave status\G;
语句查看主从同步状态,Slave_IO_Running
和 Slave_SQL_Running
的值均为 Yes
才能表示主从同步状态是正常的:
配置 Ssh 免密登录 配置集群内所有主机之间能够通过 ssh
免密登录,因为 MHA 是基于 ssh
去实现远程控制及数据管理的。例如,故障转移过程中保存原 Master 节点的二进制日志以及配置虚拟 IP 等。
1、生成 ssh
登录密钥:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 [root@master ~]# ssh-keygen Generating public/private rsa key pair. Enter file in which to save the key (/root/.ssh/id_rsa): Enter passphrase (empty for no passphrase): Enter same passphrase again: Your identification has been saved in /root/.ssh/id_rsa. Your public key has been saved in /root/.ssh/id_rsa.pub. The key fingerprint is: SHA256:LzRXziRQPrqaKEteH6KrZpCiV6uGP6GTi6RonE7Hhms root@master The key's randomart image is: + ---[RSA 2048] ----+ | ... | | o | | + o | | . B | | . S . o | |+ + . . = | |=Bo*o.. o . | |%EOo.+ + . | |%XB*. + | + ----[SHA256] -----+
2、将密钥拷贝到其他服务器上:
1 2 3 4 [root@master ~]# ssh-copy-id -i /root/.ssh/id_rsa root@192.168.190.151 [root@master ~]# ssh-copy-id -i /root/.ssh/id_rsa root@192.168.190.152 [root@master ~]# ssh-copy-id -i /root/.ssh/id_rsa root@192.168.190.154 [root@master ~]# ssh-copy-id -i /root/.ssh/id_rsa root@192.168.190.153
然后到集群中其他节点上进行同样的操作,由于是重复的操作这里就不演示了。最后简单测试下能否正常免密登录即可:
1 2 3 4 5 [root@master ~]# ssh root@192.168.190.152 Last failed login: Sat Feb 1 15:29:38 CST 2020 from 192.168.190.151 on ssh:notty There was 1 failed login attempt since the last successful login. # 没有要求输入密码,测试成功 Last login: Sat Feb 1 14:14:03 2020 from 192.168.190.1 [root@slave-01 ~]#
安装 MHA 软件包 1、首先在所有的节点上安装 mha4mysql-node
软件包,安装包可到如下地址进行下载:
下载好的 rpm
文件如下:
1 2 3 [root@master ~]# ls *.rpm mha4mysql-node-0.58-0.el7.centos.noarch.rpm [root@master ~]#
在安装该 rpm
包之前需要先安装 perl 相关依赖:
1 2 [root@master ~]# yum -y install epel-release [root@master ~]# yum -y install perl-DBD-MySQL perl-DBI ncftp
现在就可以安装 mha4mysql-node
了,命令如下:
**Tips:** 另外的两个 Slave 节点和监控节点按如上步骤安装即可,这里就不重复演示了
2、接着是在监控节点 manager
上安装 mha4mysql-manager
软件包,安装包到如下地址进行下载:
1 2 [root@master ~]# rpm -ivh mha4mysql-node-0.58-0.el7.centos.noarch.rpm
下载好的 rpm
文件如下:
1 2 3 [root@manager ~]# ls *.rpm mha4mysql-manager-0.58-0.el7.centos.noarch.rpm [root@manager ~]#
同样,在安装该 rpm
包之前需要先安装 perl 相关依赖:
1 2 3 [root@manager ~]# yum -y install epel-release [root@manager ~]# yum -y install perl-Config-Tiny perl-Time-HiRes perl-Parallel-ForkManager perl-Log-Dispatch perl-DBD-MySQL ncftp
然后安装 mha4mysql-manager
包,命令如下:
1 2 [root@manager ~]# rpm -ivh mha4mysql-manager-0.58-0.el7.centos.noarch.rpm
配置 MHA 管理节点 1、创建 MHA 的配置文件存放目录和工作目录:
1 2 [root@manager ~]# mkdir /etc/mha [root@manager ~]# mkdir /home/mysql_mha
2、创建 MHA 的配置文件,并添加如下内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 [root@manager ~]# vim /etc/mha/mysql_mha.cnf [server default] # mha 用于访问数据库的账户和密码 user=mha password=Abc_123456 # 指定 mha 的工作目录 manager_workdir=/home/mysql_mha # mha 日志文件的存放路径 manager_log=/home/mysql_mha/manager.log # 指定 mha 在远程节点上的工作目录 remote_workdir=/home/mysql_mha # 可以使用 ssh 登录的用户 ssh_user=root # 用于主从复制的 MySQL 用户和密码 repl_user=repl repl_password=Abc_123456 # 指定间隔多少秒检测一次 ping_interval=1 # 指定 master 节点存放 binlog 日志文件的目录 master_binlog_dir=/var/lib/mysql # 指定一个脚本,该脚本实现了在主从切换之后,将虚拟 IP 漂移到新的 Master 上 master_ip_failover_script=/usr/bin/master_ip_failover # 指定用于二次检查节点状态的脚本 secondary_check_script=/usr/bin/masterha_secondary_check -s 192.168.190.151 -s 192.168.190.152 -s 192.168.190.154 # 配置集群中的节点信息 [server1] hostname=192.168.190.151 # 指定该节点可以参与 Master 选举 candidate_master=1 [server2] hostname=192.168.190.152 candidate_master=1 [server3] hostname=192.168.190.154 # 指定该节点不能参与 Master 选举 no_master=1
3、编写配置文件中所配置的 master_ip_failover
脚本,该脚本是根据 MHA 的官方示例修改的,MHA 默认并没有提供。需要注意脚本中的几处地方需要根据实际情况进行修改,已用注释标明:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 [root@manager ~]# vim /usr/bin/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 可以根据实际情况进行修改 my $vip = '192.168.190.80/24'; my $key = '1'; # 这里的网卡名称 “ens32” 需要根据你机器的网卡名称进行修改 my $ssh_start_vip = "sudo /sbin/ifconfig ens32:$key $vip"; my $ssh_stop_vip = "sudo /sbin/ifconfig ens32:$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"; }
还需要给该脚本添加可执行权限,否则 MHA 是无法调用的:
1 2 [root@manager ~]# chmod a+x /usr/bin/master_ip_failover
4、根据配置文件中 remote_workdir
的配置,需在其他节点上创建 MHA 的远程工作目录:
1 2 3 [root@master ~]# mkdir /home/mysql_mha [root@slave-01 ~]# mkdir /home/mysql_mha [root@slave-02 ~]# mkdir /home/mysql_mha
5、在配置文件中指定了让 manager
使用 mha
这个用户来访问数据库节点,所以需要在 master
节点上创建 mha
用户:
1 2 3 create user 'mha'@'%' identified with mysql_native_password by 'Abc_123456'; grant all privileges on *.* to 'mha'@'%'; flush privileges;
6、完成以上所有步骤后,在 manager
节点上使用 masterha_check_ssh
和 masterha_check_repl
对配置进行检查,其中 masterha_check_ssh
用于检查 ssh
登录是否正常,而 masterha_check_repl
则用于检查主从节点的复制链路是否正常:
1 2 [root@manager ~]# masterha_check_ssh --conf=/etc/mha/mysql_mha.cnf [root@manager ~]# masterha_check_repl --conf=/etc/mha/mysql_mha.cnf
执行结果如下:
7、以上检测都通过后,就可以启动 MHA 服务了。启动命令如下:
1 2 [root@manager ~]# nohup masterha_manager --conf=/etc/mha/mysql_mha.cnf &
启动完成后,可以使用 ps
命令查看 masterha_manager
进程是否存在,如下存在则代表启动成功:
1 2 3 4 [root@manager ~]# ps aux |grep masterha_manager root 2842 0.3 1.1 299648 22032 pts/0 S 18:30 0:00 perl /usr/bin/masterha_manager --conf=/etc/mha/mysql_mha.cnf root 2901 0.0 0.0 112728 976 pts/0 R+ 18:31 0:00 grep --color=auto masterha_manager [root@manager ~]#
8、最后我们需要到 master
节点上,手动去配置虚拟 IP。因为 MHA 只会在主从切换时漂移虚拟 IP 到新的 Master 节点,而不会在第一次启动时主动去设置 Master 的虚拟 IP,所以我们需要手动设置。设置虚拟 IP 的命令如下:
1 2 [root@master ~]# ifconfig ens32:1 192.168.190.80/24
设置成功后,使用 ip addr
命令可以看到网卡上绑定的虚拟 IP:
测试 MHA 服务 到此为止,我们就已经完成了 MHA 高可用架构的搭建,接下来我们对其进行一些简单的测试。例如,测试下是否能正常 ping
通虚拟 IP,毕竟应用端访问数据库时连接的是虚拟 IP,所以首先得确保虚拟 IP 是能够被访问的。如下:
能 ping
通之后,使用 Navicat 等远程连接工具测试下能否正常通过虚拟 IP 连接上数据库:
确定了虚拟 IP 能正常访问后,接着测试 MHA 是否能够正常进行主从切换,首先将 master
节点上的 MySQL 服务给停掉,模拟 Master 宕机:
1 [root@master ~]# systemctl stop mysqld
正常情况下,此时 master
节点上的网卡就不会再绑定该虚拟 IP:
而是会被 MHA 漂移到 slave-01
节点的网卡上,因为此时该 Slave 就是新的 Master:
接着进入 slave-02
节点上的 MySQL 命令行终端,确认下该 Slave 是否已经正常与新的 Master 进行同步。之前我们配置 slave-02
的主库是 master
,现在将 master
停掉后,可以看到 slave-02
的 Master_Host
已经被 MHA 切换成了 slave-01
的 IP:
经过以上测试后,可以看到我们搭建的 MHA 架构是能够正常运行的,已经使得 Replication 集群拥有了基本的高可用能力,即便 Master 下线后也能正常从 Slave 中选举新的 Master 并进行切换,也正确建立了其他 Slave 与新 Master 的复制链路。
MHA 架构优缺点 –
优点
使用 Perl 脚本语言开发并且完全开源,开发者可以根据自己的需求进行二次开发
能够支持基于 GTID 和基于日志点的复制模式
MHA 在进行故障转移时更不易产生数据丢失
在一个监控节点上可以监控多个 Replication 集群
缺点
MHA 默认不提供虚拟 IP 功能,需要自行编写脚本或利用第三方工具来实现虚拟 IP 的配置
MHA 启动后只会对 Master 进行监控,不会对 Slave 进行监控,也无法监控复制链路的情况
集群环境需要能够通过 ssh
免密登录,存在一定的安全隐患
MHA 没有提供对 Slave 的读负载均衡功能,需要通过第三方工具来实现