MHA master high availability (主节点高可用)
MHA:Master High Availability,对主节点进行监控,可实现自动故障转移至其它从节点;通过提 升某一从节点为新的主节点,基于主从复制实现,还需要客户端配合实现,目前MHA主要支持一主 多从的架构,要搭建MHA,要求一个复制集群中必须最少有三台数据库服务器,一主二从,即一台 充当master,一台充当备用master,另外一台充当从库,出于机器成本的考虑,淘宝进行了改造,目前淘宝TMHA已经支持一主一从
MHA 工作原理
1. MHA利用 SELECT 1 As Value 指令判断master服务器的健康性,一旦master宕机,MHA从宕机崩溃的master保存二进制日志事件(binlog events)前提是主服务器死的不彻底。死的彻底,就找不回来了,不能确保数据不丢失。    
2. 识别含有最新更新的slave 
3. 应用差异的中继日志(relay log)到其他的slave
4. 应用从master保存的二进制日志事件(binlog events)到所有slave节点
5. 提升一个slave为新的master 
6. 使其他的slave连接新的master进行复制 
7. 故障服务器自动被剔除集群(masterha_conf_host),将配置信息去掉 
8. 旧的Master的 VIP 漂移到新的master上,用户应用就可以访问新的Master
9. MHA是一次性的高可用性解决方案,Manager会自动退出
选举新的Master
如果设定权重(candidate_master=1),按照权重强制指定新主,但是默认情况下如果一个slave落后master二进制日志超过100M的relay logs,即使有权重,也会失效.如果设置check_repl_delay=0, 即使落后很多日志,也强制选择其为新主 
如果从库数据之间有差异,最接近于Master的slave成为新主 
如果所有从库数据都一致,按照配置文件顺序最前面的当新
数据恢复
当主服务器的SSH还能连接,从库对比主库position 或者GTID号,将二进制日志保存至各个从节点并且应用(执行save_binary_logs 实现) 
当主服务器的SSH不能连接, 对比从库之间的relaylog的差异(执行apply_diff_relay_logs[实现])
注意
为了尽可能的减少主库硬件损坏宕机造成的数据丢失,因此在配置MHA的同时建议配置成MySQL的半同步复制
实现 MHA 实战案例(四台机器 一台MHA管理节点、一台主节点、两台从节点)
环境:四台主机
10.0.0.7 CentOS7 MHA管理端  MHA的管理节点必须是centos7
10.0.0.8 CentOS8 MySQL8.0   master
10.0.0.18 CentOS8 MySQL8.0  slave1 
10.0.0.28CentOS8MySQL8.0    slave2
管理节点两个安装包:
mha4mysql-manager  
mha4mysql-node  
其他所有节点只安装node包:
mha4mysql-node
下载
https://github.com/yoshinorim/mha4mysql-manager/wiki/Downloads https://github.com/yoshinorim/mha4mysql-node/releases/tag/v0.58 https://github.com/yoshinorim/mha4mysql-node/releases/tag/v0.58

安装:
yum -y install mha4mysql-manager-0.58-0.el7.centos.noarch.rpm  centos7安装manager包和node包
yum -y install mha4mysql-node-0.58-0.el7.centos.noarch.rpm     其他所有节点安装node包
在所有节点实现相互之间 ssh key 验证
ssh-keygen                     四台机器公用一个公钥私钥   
ssh-copy-id 127.0.0.1
rsync -av .ssh 10.0.0.8:/root/
rsync -av .ssh 10.0.0.18:/root/
rsync -av .ssh 10.0.0.28:/root/
在管理节点建立配置文件 注意: 此文件的行尾不要加空格等符号
mkdir /etc/mastermha/
vim /etc/mastermha/app1.cnf  存放管理节点配置
[server default]
user=mhauser                 #用于远程连接MySQL所有节点的用户,需要有管理员的权限
password=123456 
manager_workdir=/data/master/app1/            #目录会自动生成,无需手动创建manager_log=/data/mastermha/app1/manager.log  #日志文件
remote_workdir=/data/master/app1/             
ssh_user=root          #用于实现远程ssh基于KEY的连接,访问二进制日志
repl_user=repluser     #主从复制的用户信息
repl_password=123456 
ping_interval=1        #健康性检查的时间间隔,检查命令:选择1作为值master_ip_failover_script=/usr/local/bin/master_ip_failover  #切换VIP的perl脚本,不支持跨网络,也可用Keepalived实现
report_script=/usr/local/bin/sendmail.sh     #当执行报警脚本
check_repl_delay=0#默认值为1,表示如果slave中从库落后主库relay log超过100M,主库不会选择这个从库为新的master,因为这个从库进行恢复需要很长的时间。通过设置参数check_repl_delay=0,mha触发主从切换时会忽略复制的延时,对于设置candidate_master=1的从库非常有用,这样确保这个从库一定能成为最新的master master_binlog_dir=/data/mysql/#指定二进制日志存放的目录,mha4mysql-manager-0.58必须指定,之前版本不需要指定
[server1]
hostname=10.0.0.8
port=3306
candidata_master=1
[server2]
hostname=10.0.0.18
port=3306
[server3]
hostname=10.0.0.28
port=3306
candidata_maste=1#设置为优先候选master,即使不是集群中事件最新的slave,也会优先当主服务器

不加注释配置:
[server default] 
user=mhauser 
password=123456 
manager_workdir=/data/mastermha/app1/ 
manager_log=/data/mastermha/app1/manager.log 
remote_workdir=/data/mastermha/app1/ 
ssh_user=root 
repl_user=repluser 
repl_password=123456 
ping_interval=1 
master_ip_failover_script=/usr/local/bin/master_ip_failover report_script=/usr/local/bin/sendmail.sh 
check_repl_delay=0 
master_binlog_dir=/data/mysql/ 

[server1] 
hostname=10.0.0.8 
candidate_master=1 
[server2] 
hostname=10.0.0.18  
[server3] 
hostname=10.0.0.28
candidate_master=1
在mysql主节点修改配置文件
vim /etc/my.cnf
server_id=1
log_bin=/data/mysql/mysql-bin  #如果目录不存在,需要创建目录,并更改所有者所属组为mysql
relay_log_purge=0              #禁止自动删除不再使用的relay log,可用于同步日志
skip_name_resolve=1            #禁止反向解析,此项可选
general_log                 #方便观察的设置,生产中无需启用  可临时加 set golbal general_log=1
重启mysql服务
在mysql上创建授权帐号 让mha用来连接
mysql> create user mhauser@'10.0.0.%' identified by '123456';
mysql> grant all on *.* to mhauser@'10.0.0.%';
在管理节点执行脚本
cd /usr/local/bin/
把脚本master_ip_failover拖进来
打开vim master_ip_failover修改 $vip ='10.0.0.100/24'; 如果和物理机ip冲突,关闭物理机 网卡名要一样
加权限 chmod +x master_ip_failover
在主节点上加ip:ifconfig eth0:1 10.0.0.100/24 vip临时配到主节点上,坏了自动迁移到从节点上

cd /usr/local/bin/  
把脚本sendmail.sh拖进来
vim sendmail.sh                   #定义接收人
echo "MHA is failover" | mail -s "MHA Warning"  5435435@qq.com     133880902
加权限 chmod +x sendmail.sh

如果向往互联网发邮件 
yum -y install mailx 
打开配置文件在最下面填写你的邮箱信息
在QQ邮箱开启授权码
设置-账户-开启服务 pop3/smtp服务开启 生成授权码
vim /etc/mail.rc                 #定义发件人
set from=1153454651@qq.com
set smtp=smtp.qq.com
set smtp-auth-user=1153454651@qq.com
set smtp-auth-password=授权码
bash .sendmail.sh 发邮件
实现slave
vim /etc/my.cnf
server_id=18
log_bin=/data/mysql/mysql-bin
#如果二进制文件没有在/data/mysql下,#需要创建目录
#mkdir -p /data/mysql
#chown mysql.mysql /data/mysql
read_only
relay_log_purge=0              #禁止自动删除不再使用的relay log,可用于同步日志
skip_name_resolve=1            #禁止反向解析,此项可选
general_log                    #方便观察的设置,生产中无需启用
重启服务
检查MHA的环境
检查环境
masterha_check_ssh --cnotallow=/etc/mastermha/app1.cnf
masterha_check_repl --cnotallow=/etc/mastermha/app1.cnf
查看状态
masterha_check_status --cnotallow=/etc/mastermha/app1.cnf
启动MHA(只检查主节点的健康性)
开启MHA,默认是前台运行,生产环境一般为后台执行:
nohup masterha_manager --cnotallow=/etc/mastermha/app1.cnf --remove_dead_master_conf --ignore_last_failover &> /dev/null
环境测试开启:
masterha_manager --cnotallow=/etc/mastermha/app1.cnf --remove_dead_master_conf --ignore_last_failover
查看MHA日志(等待主mysql节点挂掉):tail -f /data/mastermha/app1/manager.log
查看主mysql节点通用日志文件:tail -f /var/lib/mysql/rocky.log  (1s扫描一次,MHA检查主节点的健康性)

如果想停止后台执行的MHA,可以执行下面命令
masterha_stop --cnotallow=/etc/mastermha/app1.cnf 
stopped app1 successfully.
查看状态
masterha_check_status --cnotallow=/etc/mastermha/app1.cnf
挂掉主节点,指定的从节点变成了主节点
挂掉主节点:原来设置的从节点会自动成为主节点。虽然从节点配置文件中是read_only,但是在mysql中select @@read_only 的查询结果已经为0,也需要手动把配置文件中的read_only注释,要不然下次重启服务后,就会变成只读。
查看ip,已经看到vip飘到了现在的主节点上
如果MHA节点没有把从节点切换成功,MHA程序不会退出,原因是由于更改了二进制存储位置,使主从无法复制
解决办法:需要重新执行主从复制后再进行切换
1、关闭线程,并清除主从复制信息
mysql > stop slave;
mysql > reset slave all;

2、查看当前主mysql二进制文件和位置
mysql > show mysql logs;

3、查看主mysql的 CHANGE MASTER TO信息 (help change master to可获得信息)

4、把主的当前二进制文件和位置、还有CHANGE MASTER TO信息进行编写并在从mysql中执行
CHANGE MASTER TO
  MASTER_HOST='10.0.0.8',         #主服务器地址
  MASTER_USER='repluser',           #用户
  MASTER_PASSWORD='123456',         #密码
  MASTER_PORT=3306,       
  MASTER_LOG_FILE='binlog.000002',  #主服务器二进制日志文件名
  MASTER_LOG_POS=196;
  
5、启动线程
mysql > start slave;

6、查看从mysql的状态
mysql > show slave status\G   io线程和dump线程都为yes

7、开启MHA
masterha_manager --cnotallow=/etc/mastermha/app1.cnf --remove_dead_master_conf --ignore_last_failover

8、挂掉主mysql节点
systemctl stop mysqld

9、MHA程序切换完成并自动退出,日志文件会显示发送邮件
修复主从
修复故障的主库,保证数据同步 
修复主从,手工新故障库加入新的主,设为为从库 
修复manager的配置文件 
清理相关目录 检查ssh互信和replication的复制是否成功 
检查VIP,如果有问题,重新配置VIP 
重新运行MHA,查询MHA状态,确保运行正常
MHA只能漂移依次,如果再次运行MHA,需要先删除下面文件
rm -rf /data/mastermha/app1/
rm -rf /data/mastermha/app1/manager.log
rm -rf /data/mastermha/app1/
然后再重新启动

MHA短暂的切换会造成用户访问的卡顿,甚至造成一部分数据的丢失,虽然是高可用的解决方案,但是不能确保数据不丢失,切换的时候,如果主节点数据和从节点有差异,比如复制有延迟,一旦切换,会造成新的主节点数据不全。