一、简介
MHA(Master HA)是一款开源的 MySQL 的高可用程序,它为 MySQL 主从复制架构提供了 automating master failover 功能。MHA 在监控到 master 节点故障时,会提升其中拥有最新数据的 slave 节点成为新的master 节点,在此期间,MHA 会通过于其它从节点获取额外信息来避免一致性方面的问题。MHA 还提供了 master 节点的在线切换功能,即按需切换 master/slave 节点。
MHA 服务有两种角色, MHA Manager(管理节点)和 MHA Node(数据节点): MHA Manager: 通常单独部署在一台独立机器上管理多个 master/slave 集群(组),每个 master/slave 集群称作一个 application,用来管理统筹整个集群。 MHA node: 运行在每台 MySQL 服务器上(master/slave/manager),它通过监控具备解析和清理 logs 功能的脚本来加快故障转移。
由上图我们可以看出,每个复制组内部和 Manager 之间都需要ssh实现无密码互连,只有这样,在 Master 出故障时, Manager 才能顺利的连接进去,实现主从切换功能。
二、工作原理
(1) 从宕机崩溃的 master 保存二进制日志事件(binlog events);
(2) 识别含有最新更新的 slave ;
(3) 应用差异的中继日志(relay log) 到其他 slave ;
(4) 应用从 master 保存的二进制日志事件(binlog events);
(5) 提升一个 slave 为新 master ;
(6) 使用其他的 slave 连接新的 master 进行复制。
三、MHA实现
3.1环境准备
3.1.1准备四台虚拟机(均为centos 7.x )
3.1.2 更换yum源
3.1.3关闭防火墙,禁用SELinux
3.1.4 host配置
在不同的机器上配置名字和IP地址
机器名称 | IP配置 | 服务角色 | 备注 |
---|---|---|---|
manager | 172.16.90.211 | manager控制器 | 用于监控管理 |
master | 172.16.90.212 | 数据库主服务器 | 开启bin-log relay-log 关闭relay_log |
slave1 | 172.16.90.213 | 数据库从服务器 | 开启bin-log relay-log 关闭relay_log |
slave2 | 172.16.90.214 | 数据库从服务器 | 开启bin-log relay-log 关闭relay_log |
根据上表 名字要在不同的机器上分别输入如下命令
hostnamectl set-hostname managermastersalve1salve2
IP地址在其中一台输入即可
[root@node4 ~]# cat >> /etc/hosts << EOF
> 172.16.90.111 manager
> 172.16.90.112 master
> 172.16.90.113 slave1
> 172.16.90.114 slave2
> EOF
3.2初始主节点 master 的配置
【master】
3.2.1解压·
将mysql-8.0.18-1.el7.x86_64.rpm-bundle.tar包下载后复制到master虚拟机,再从这个虚拟机拷贝到slave1和slave2虚拟机的~目录
scp mysql-8.0.18-1.el7.x86_64.rpm-bundle.tar slave1:~
安装途中四个包,安装时可能会发现缺少依赖,
安装后我这里显示有个包需要移除
[rootnode2 MySQL]# yum remove mariadb-libs
3.2.2配置 master 文件
修改 master 的数据库配置文件来对其进行初始化配置
在如图所示的地方插入两段话
vim /etc/my.cnf
3.3 slave 节点依赖的配置
主(master)配置后,从(slave1,slave2)也配置该文件:其他不变,从的server-id需要改为113,114,最后一行需要加上relay_log_purge = 0
三台机器配置完文件后,均重启服务
[root@master ~]# systemctl restart mysql.server
查看有无密码
【master】
【slave】 两个slave机器都是相同的操作
免密登陆配置
【master】
在my.conf配置文件里插入一行
3.4配置一主多从复制架构
【master】
[root@node2 MySQL1]# mysql#先创建用户
(rootalocalhost) [(none)] >create user 'slave'@'172.16.90.%' identified with mysql_native_password by 'MySQL@123';
Query OK,0 rows affected(0.01 sec)#授权
(root@localhost) [(none)]>grant replication slave,replication client on *.* to 'slave'@'172.16.90.%';
Query OK, 0 rows affected, 1 warning (0.01 sec)
【slave】
[root@node2 MySQL1]# mysql(rootalocalhost)[(none)> change master to-> master host='172.16.90.112',-> master user='slave',-> master password='MySQL@123',-> master auto position=l;
Query OK,0 rows affected,2 warnings(0.10 sec)#开启主从同步
(rootalocalhost)[(none)> start slave;
Query OK,0 rows affected (0.00 sec)
(rootalocalhost)[(none)> show slave status \G
*************************** 1. row ***************************Slave_IO_State: Waiting for master to send eventMaster_Host: 172.16.90.212Master_User: slaveMaster_Port: 3306Connect_Retry: 60Master_Log_File: mysql-bin.000002Read_Master_Log_Pos: 712Relay_Log_File: relay-log.000002Relay_Log_Pos: 925Relay_Master_Log_File: mysql-bin.000002Slave_IO_Running: YesSlave_SQL_Running: Yes
...
3.5安装配置MHA
3.5.1在 master 上进行授权
在所有 Mysql 节点授权拥有管理权限的用户可在本地网络中有其他节点上远程访问。
先创建用户再授权
3.5.2准备ssh互通环境
MHA集群中的各节点彼此之间均需要基于ssh互信通信,以实现远程控制及数据管理功能。接下来我们需要对四个节点进行设置生成密钥对,都拷贝到管理(master)节点
[root@all ~]# ssh-keygen -f ~/.ssh/id_rsa -P '' -q[root@all ~]# ssh-copy-id manager#拷贝免密钥
[root@node1 ~]# scp ~/.ssh/authorized_keys master:~/.ssh/
root@node2's password:
authorized_keys 100% 1598 3.4MB/s 00:00 [root@node1 ~]# scp ~/.ssh/authorized_keys slave1:~/.ssh/
root@node3's password:
authorized_keys 100% 1598 2.9MB/s 00:00 [root@node1 ~]# scp ~/.ssh/authorized_keys slave2:~/.ssh/
root@node4's password:
authorized_keys 100% 1598 2.9MB/s 00:00
验证免密钥登陆(每个机器都要验证,第一次登陆需要手动输入yes,后面就不需要了)
[root@node4 ~]# for i in manager master slave1 slave2;do ssh $i hostname;done
3.5.3 安装 MHA 包
安装包下载地址:
mha官网:https://code.google.com/archive/p/mysql-master-ha/
github下载地址:
https://github.com/yoshinorim/mha4mysql-manager/releases/tag/v0.58
https://github.com/yoshinorim/mha4mysql-node/releases/tag/v0.58
Manager节点需要另外多安装一个包(manager和node ) ,MHA的Node依赖于perl-DBD-MySQL,所以配置epel源。
【manager】下载两个包,把其中一个拷贝给其他节点
[root@node1 ~]# wget -c https://github.com/yoshinorim/mha4mysql-manager/releases/download/v0.58/mha4mysql-manager-0.58-0.el7.centos.noarch.rpm
[root@node1 ~]# wget -c https://github.com/yoshinorim/mha4mysql-node/releases/download/v0.58/mha4mysql-node-0.58-0.el7.centos.noarch.rpm
【all】:所有的机器
[root@node1 ~]# wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
[root@node1 ~]# yum install mha4mysql-*.rpm
【master】
由于直接安装存在依赖缺失和版本不一致问题,最后从mysql官网上下载了yum源文件(mysql84-community-release-el7-1.noarch.rpm),这里我就不具体写是怎么下载的了,大家去mysql官网找找
下载源到虚拟机后,拷贝到其他三个节点
拷贝后先安装一下源,再安装node
yum install mysql84-community-release-el7-1.noarch.rpmyum install mha4mysql-node-0.58-0.el7.centos.norach.rpm
【slave】同理
yum install mysql84-community-release-el7-1.noarch.rpmyum install mha4mysql-node-0.58-0.el7.centos.norach.rpm
【manager】同理,不过需要多安装一个manager包
yum install mysql84-community-release-el7-1.noarch.rpmyum install mha4mysql-node-0.58-0.el7.centos.norach.rpm mha4mysql-manager-0.58-0.el7.centos.noarch.rpm
3.5.4 MHA配置
Manager 节点需要为每个监控的 master/slave 集群提供一个专用的配置文件,而所有的 master/slave 集群也可共享全局配置。全局配置文件默认为/etc/masterha_default.cnf
,其为可选配置。如果仅监控一组 master/slave 集群,也可直接通过 application 的配置来提供各服务器的默认配置信息。
3.5.5 定义 MHA 管理配置文件
创建一个目录存放MHA,方便管理
创建配置文件目录
mkdir /etc/mha
创建日志目录
mkdir -p /var/log/mha/app1vim /etc/mha/app1.cnf
[server default]
user=mhaadmin
password=Mha@1234
manager_workdir=/var/log/mha/app1
manager_log=/var/log/mha/app1/manager.log
ssh_user=root
repl_user=slave
repl_password=MySQL@123
ping_interval=1
[server1]
hostname=172.16.90.112
ssh_port=22
candidate_master=1
[server2]
hostname=172.16.90.113
ssh_port=22
candidate_master=1
[server3]
hostname=172.16.90.114
ssh_port=22
candidate_master=1检查文件有无特殊字符
cat -v /etc/mha/app1.cnf
3.5.6 检测节点
1)检测各节点间 ssh 互信通信配置是否 ok
[root@node1 ~]# masterha_check_ssh --conf=/etc/mha/app1.cnf
...
Wed Nov 24 11:36:56 2021 - [debug] Connecting via SSH from root@172.16.90.212(172.16.90.212:22) to root@172.16.90.213(172.16.90.213:22)..
Wed Nov 24 11:36:56 2021 - [debug] ok.
...2)检查管理的MySQL复制集群的连接配置参数是否OK
[root@node1 ~]# masterha_check_repl --conf=/etc/mha/app1.cnf
...
Wed Nov 24 11:37:55 2021 - [info] Got exit code 0 (Not master dead).MySQL Replication Health is OK.
3.6 启动MHA
[root@node1 ~]# nohup masterha_manager --conf=/etc/mha/app1.cnf --remove_dead_master_conf --ignore_last_failover < /dev/null > /var/log/mha/app1/manager.log 2>&1 &
[1] 11457
查看一下 master 节点的状态:
[root@node1 ~]# masterha_check_status --conf=/etc/mha/app1.cnf
app1 (pid:11457) is running(0:PING_OK), master:172.16.90.212
查看监控日志
[root@node1 ~]# tail -f /var/log/mha/app1/manager.log
172.16.90.212(172.16.90.212:3306) (current master)+--172.16.90.213(172.16.90.213:3306)+--172.16.90.214(172.16.90.214:3306)Wed Nov 24 11:45:30 2021 - [warning] master_ip_failover_script is not defined.
Wed Nov 24 11:45:30 2021 - [warning] shutdown_script is not defined.
...
Wed Nov 24 11:45:30 2021 - [info] Starting ping health check on 172.16.90.212(172.16.90.212:3306)..
Wed Nov 24 11:45:30 2021 - [info] Ping(SELECT) succeeded, waiting until MySQL doesn't respond..
3.6.1 开发启动服务脚本
工作中启动太麻烦了,所以找了一个脚本作为启动服务
路径一样可以用,不一样得改
[root@node1 ~] vim /etc/init.d/masterha_managerd
#!/bin/bash
# chkconfig: 35 80 20
# description: MHA management script.STARTEXEC="/usr/bin/masterha_manager --conf"
STOPEXEC="/usr/bin/masterha_stop --conf"
CONF="/etc/mha/app1.cnf"
process_count=`ps -ef |grep -w masterha_manager|grep -v grep|wc -l`
PARAMS="--ignore_last_failover"case "$1" instart)if [ $process_count -gt 1 ]thenecho "masterha_manager exists, process is already running"elseecho "Starting Masterha Manager"$STARTEXEC $CONF $PARAMS < /dev/null > /var/log/mha/app1/manager.log 2>&1 &fi;;stop)if [ $process_count -eq 0 ]thenecho "Masterha Manager does not exist, process is not running"elseecho "Stopping ..."$STOPEXEC $CONFwhile(true)doprocess_count=`ps -ef |grep -w masterha_manager|grep -v grep|wc -l`if [ $process_count -gt 0 ]thensleep 1elsebreakfidoneecho "Master Manager stopped"fi;;*)echo "Please use start or stop as first argument";;
esac
[root@node1 ~] chmod +x /etc/init.d/masterha_managerd添加成启动服务:
[root@node1 ~] chkconfig --add masterha_managerd
[root@node1 ~] chkconfig masterha_managerd on
3.6.2 测试服务脚本
脚本和命令不能同时启动,可能会有问题,先关闭进程
开启脚本:
[root@node1 ~] systemctl start masterha_managerd
[root@node1 ~] systemctl status masterha_managerd
● masterha_managerd.service - SYSV: MHA management script.Loaded: loaded (/etc/rc.d/init.d/masterha_managerd; bad; vendor preset: disabled)
...停止脚本:
[root@node1 ~]# systemctl stop masterha_managerd
看进程:
[root@node1 ~]# ps -ef | grep -w masterha_manager
root 25856 1169 0 15:24 pts/0 00:00:00 grep --color=auto -w masterha_manager
3.7 配置VIP
为了防止脑裂发生,推荐生产环境采用脚本的方式来管理虚拟ip,而不是使用keepalived来完成。
脑裂:由于互相争抢资源而导致得一种异常,检测不到对方存活信息
1.编写脚本
[root@node1 ~] vim /usr/local/bin/master_ip_failover
#!/usr/bin/env perluse 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 = '172.16.90.210/24';
my $key = '1';
my $ssh_start_vip = "/sbin/ifconfig eth0:$key $vip";
my $ssh_stop_vip = "/sbin/ifconfig eth0:$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";
}[root@node1 ~] chmod +x /usr/local/bin/master_ip_failover
注意脚本两个地方:网段和接口
2、更改manager配置文件
[root@node1 ~]# vim /etc/mha/app1.cnf
[server default]
添加:
master_ip_failover_script=/usr/local/bin/master_ip_failover
3、主库上,手工生成第一个vip地址
[root@node2 ~]# ifconfig eth0:1 172.16.90.210/24
注意:第一次需要在主库上手动配置vip
[root@node2 ~]# ifconfig -a |grep -A 2 "eth0:1"
eth0:1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500inet 172.16.90.210 netmask 255.255.255.0 broadcast 172.16.90.255ether 28:6e:d4:89:3b:3e txqueuelen 1000 (Ethernet)
4、重启MHA
[root@node1 ~]# systemctl restart masterha_managerd