1、MHA的设计原理 (Failover 过程)

1.1、master启动参数介绍

  1. 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 &
  2. --conf=/etc/mha/app1.cnf: 启动的配置文件, 可以配置多套, 一套主从环境一套配置启动
  3. --remove_dead_master_conf: MySQL master宕机, 则从配置中移除
  4. --ignore_last_failover: 忽略上次故障转移, 默认8小时内不能再发生故障转移

1.2、监控

/usr/bin/masterha_master_monitor
每隔 ping_interval秒探测1次, 连续4次还没有, 说明主库宕机

#底层原理, MHA master每隔几秒链接主库, 执行命令, 有返回则表示存活
mysql -umha -pmha -h 主库IP -P 3306 -e "select user();"

1.3、选新主

1. 日志量
2. 备选主
3. 哪些不被选主
  no_master=1
  log_bin #二进制日志没开
  check_slave_delay #如果从库落后主库100M的日志量, (可以关闭)

1.4、数据补偿

1. 原主库ssh能连接  
     各个从节点调用: save_binary_logs 脚本, 立即保存缺失部分的binlog到各自节点/var/tmp目录

2. 原主库ssh不能连接  
   从节点调用apply_diff_relay_logs, 进行relay-log日志差异补偿

3. 额外数据补偿 (主库日志冗余机制)
   binlog_server

1.5、切换

所有从库解除主从身份: stop slave ; reset slave;
重构新的主从关系: change master to xxx

1.6、应用透明 (vip)

1.7、故障提醒

1.8、额外数据补偿

1.9、剔除故障节点

1.10、manager 程序 “自杀”

2、应用透明 (VIP)

2.1、介绍

#作用网卡
  eth0:1 
  ens33:1

#IP
  vip : 192.168.10.15/24
  一定是一个空闲地址
  一定要和对外提供服务的地址同一网段
  不能跨网段

2.1、VIP 故障转移脚本

MHA-master节点

#解压
yum -y install unzip
unzip mha_script.zip
cd mha_script
\cp -a * /usr/local/bin/

#授权
chmod +x /usr/local/bin/*

#转字符编码
yum -y install dos2unix net-tools
dos2unix /usr/local/bin/*

2.2、修改内容

vim  /usr/local/bin/master_ip_failover

#修改参数
my $vip = '192.168.10.15/24';
my $key = '1';
my $if  = 'ens33';
my $ssh_start_vip = "/sbin/ifconfig $if:$key $vip";
my $ssh_stop_vip = "/sbin/ifconfig  $if:$key down";
my $ssh_Bcast_arp= "/sbin/arping -I $if -c 3 -A 192.168.10.15";

#参数解释
my $vip = '192.168.10.15/24';  #VIP
my $key = '1';                 #ens33:1中的1
my $if  = 'ens33';             #网卡名
my $ssh_start_vip = "/sbin/ifconfig $if:$key $vip";
my $ssh_stop_vip = "/sbin/ifconfig  $if:$key down";
my $ssh_Bcast_arp= "/sbin/arping -I $if -c 3 -A 192.168.10.15";

2.3、修改 manager 配置文件

vim /etc/mha/app1.cnf
#添加 [server default] 区域内
master_ip_failover_script=/usr/local/bin/master_ip_failover

注意:
需要与 master_ip_failover脚本实际位置对应

2.4、重启MHA

masterha_stop  --conf=/etc/mha/app1.cnf
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 &

2.5、手工在主库添加 VIP

#首次需要手动在主库执行, 当前环境主库为db01, 192.168.10.11
ifconfig ens33:1 192.168.10.15/24

#查看主库信息
masterha_check_status --conf=/etc/mha/app1.cnf

3、故障提醒功能

3.1、准备脚本

vim /usr/local/bin/send_report
#修改参数
my $smtp='smtp.qq.com';
my $mail_from='2071392283@qq.com';
my $mail_user='2071392283';
my $mail_pass='mdtszifxlofgdiga';
my $mail_to=['2071392283@qq.com'];
#my $mail_to=['to1@qq.com','to2@qq.com'];

#参数解释
my $smtp='smtp.qq.com';             #smtp服务器
my $mail_from='2071392283@qq.com';  #发件箱
my $mail_user='2071392283';         #用户名 QQ号
my $mail_pass='mdtszifxlofgdiga';   #授权码
my $mail_to=['2071392283@qq.com'];  #收件箱
#my $mail_to=['to1@qq.com','to2@qq.com'];  #多个邮箱配置

3.2、修改 MHA-master配置文件

vim /etc/mha/app1.cnf
#添加一行 
report_script=/usr/local/bin/send_report

3.3、重启 MHA-master

masterha_stop  --conf=/etc/mha/app1.cnf
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 &

4、日志补偿的冗余方案

—binlog_server

4.1、创建必要目录 (db03)

#创建一个目录保存binlog, 不能与当前mysql_binlog目录在一起
mkdir -p /data/binlog_server/
chown -R mysql.mysql /data/*
cd  /data/binlog_server/

#查看正在同步的 binlog文件
mysql -e "show slave status \G"| grep "Master_Log"

#同步主库 binlog, 然后敲回车, 后台运行
mysqlbinlog  -R --host=192.168.10.11 --user=mha --password=mha --raw  --stop-never mysql-bin.000001 &

#查看进程状态
ps aux | grep mysqlbinlog

注意:
拉取日志的起点, 需要按照目前从库的已经获取到的二进制日志点为起点

#当前环境正在同步的binlog文件是 mysql-bin.000001
mysql -e "show slave status \G"| grep "Master_Log"
  Master_Log_File: mysql-bin.000001
  Read_Master_Log_Pos: 2017
  Relay_Master_Log_File: mysql-bin.000001
  Exec_Master_Log_Pos: 2017

4.2、配置文件设置

vim /etc/mha/app1.cnf
#末尾添加
[binlog1]
no_master=1
hostname=192.168.10.13
master_binlog_dir=/data/binlog_server/

4.3、重启MHA

masterha_stop  --conf=/etc/mha/app1.cnf
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 &

5、MHA高可用-故障模拟

5.1、故障模拟

MySQL主节点模拟故障 (db01)

/etc/init.d/mysqld stop

MHA-master 监控日志

tail -f /var/log/mha/app1/manager

5.2、检查故障

1. MHA-master 死亡
ps aux | grep masterha_manager

2. MHA-binlog_server 死亡
ps aux | grep mysqlbinlog

3. MHA-master 配置文件变化
#会将死亡的节点, 移除配置

4. MySQL主节点发生变化
mysql -e "show slave status\G" | grep -i "master_host"

5. VIP发生转移
ifconfig

6. QQ邮件提醒

6、故障恢复

6.1、检查主从关系

1. mysql -e "show slave status\G" | grep -i "master_host"

2. 修复主从 db01
/etc/init.d/mysqld start

CHANGE MASTER TO
   MASTER_HOST='192.168.10.12',
   MASTER_PORT=3306,
   MASTER_USER='slave',
   MASTER_PASSWORD='123',
   MASTER_AUTO_POSITION=1;

start slave;

show slave status\G
mysql -e "show slave status\G" | grep -i "master_host"

6.2、检查VIP是否在主库

ifconfig

6.3、检查binlog_server

#检查binlog_server状态, 删除旧binlog
ps aux | grep mysqlbinlog
cd /data/binlog_server/
rm -rf /data/binlog_server/*

#拉取新主库日志
mysql -e "show slave status \G"| grep "Master_Log"
mysqlbinlog  -R --host=192.168.10.12 --user=mha --password=mha --raw  --stop-never mysql-bin.000001 &

6.4、检查 MHA-master配置

方法一: vim

方法二: 调用脚本
#增加节点, 将原来的master节点加入配置, cat /etc/mha/app1.cnf
masterha_conf_host --command=add --conf=/etc/mha/app1.cnf --hostname=192.168.10.11 --block=server1 --params="port=3306"

#删除节点 (拓展)
masterha_conf_host --command=delete --conf=/etc/mha/app1.cnf --block=server1

6.5、检查ssh互信和mysql主从复制

masterha_check_ssh  --conf=/etc/mha/app1.cnf
masterha_check_repl  --conf=/etc/mha/app1.cnf

6.6、启动MHA-master

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 &

#检查 MySQl master节点
masterha_check_status   --conf=/etc/mha/app1.cnf

7、MHA的维护操作-在线切换演练

master_ip_online_change_script
功能: 在线切换时、自动锁原主库、VIP自动切换

切换演练:
192.168.10.11 主库 192.168.10.12、192.168.10.13 从库
切换主库
192.168.10.12 主库 192.168.10.11、192.168.10.13 从库

准备切换脚本

vim /usr/local/bin/master_ip_online_change
#修改配置 VIP
my $vip = "192.168.10.15/24";
my $key = "1";
my $ssh_start_vip = "/sbin/ifconfig ens33:$key $vip";
my $ssh_stop_vip = "/sbin/ifconfig ens33:$key $vip down";
my $ssh_Bcast_arp= "/sbin/arping -I ens33 -c 3 -A 192.168.10.15";

修改MHA配置文件

vim /etc/mha/app1.cnf
# [server default] 区域添加
master_ip_online_change_script=/usr/local/bin/master_ip_online_change

停止 MHA-master

masterha_stop  --conf=/etc/mha/app1.cnf

检查主从复制

masterha_check_repl   --conf=/etc/mha/app1.cnf

# 正确输出信息
MySQL Replication Health is NOT OK!

在线切换

masterha_master_switch  --conf=/etc/mha/app1.cnf --master_state=alive --new_master_host=192.168.10.12 --orig_master_is_new_slave --running_updates_limit=10000

参数解释:
--conf=/etc/mha/app1.cnf: 配置文件
--master_state=alive: 主库状态为存活状态
--new_master_host=192.168.10.12: 新主库IP
--orig_master_is_new_slave: 原始主库是新主库的从库
--running_updates_limit=10000: 网络延迟限制, (单位:ms, 10秒, 通过ping命令查看); 超出则不会发生切换

提示解释:
It is better to execute FLUSH NO_WRITE_TO_BINLOG TABLES on the master before switching. Is it ok to execute on 192.168.10.11(192.168.10.11:3306)? (YES/no):yes
#FLUSH NO_WRITE_TO_BINLOG TABLES: 主库全局锁, 不能写入

Starting master switch from 192.168.10.11(192.168.10.11:3306) to 192.168.10.12(192.168.10.12:3306)? (yes/NO):yes
#from 主库 to 新主库: 主库切换

Switching master to 192.168.10.12(192.168.10.12:3306) completed successfully.
#主库切换成功

重构 binlogserver

#停止 mysqlbinlog进程
ps -ef | grep mysqlbinlog
kill -9 xxx

#清除旧binlog, 重新请求新主库的binlog
mysql -e "show slave status \G"| grep "Master_Log"
cd /data/binlog_server/
rm -rf *
mysqlbinlog  -R --host=192.168.10.12 --user=mha --password=mha --raw  --stop-never mysql-bin.000001 &

启动 MHA-master

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 &

检查新主库

#查看主库状态信息
masterha_check_status   --conf=/etc/mha/app1.cnf

#检查VIP是否转移到新的主库
ifconfig
ens33:1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.10.15  netmask 255.255.255.0  broadcast 192.168.10.255

#检查主库是否正常, 不是从库
mysql -e "show slave status\G"