1. MHA的简单介绍

简介

MHA(Master High Availability)目前在MySQL高可用方面是一个相对成熟的解决方案,它由日本DeNA公司youshimaton(现就职于Facebook公司)开发,是一套优秀的作为MySQL高可用性环境下故障切换和主从提升的高可用软件。在MySQL故障切换过程中,MHA能做到在0~30秒之内自动完成数据库的故障切换操作,并且在进行故障切换的过程中,MHA能在最大程度上保证数据的一致性,以达到真正意义上的高可用

已托管至github,对应地址如下

manager地址,https://github.com/yoshinorim/mha4mysql-manager
node地址,https://github.com/yoshinorim/mha4mysql-node
截止本文档编写时间为止,最新版本为0.58

优点

可参考官方文档详细介绍 https://github.com/yoshinorim/mha4mysql-manager/wiki/Advantages 大致总结如下:

1、主从切换非常迅速,通常10-30s
2、最大程度上解决数据一致性的问题
3、不需要修改当前已有的MySQL架构和配置
4、不需要另外多余的服务器
5、没有性能损耗
6、没有存储引擎限制

  

2. MHA的搭建概述

数据库架构:一主两从

master:192.168.142.48
slave1:192.168.142.49
slave2:192.168.142.50

mha架构:

manager:192.168.142.49
node:192.168.142.48,192.168.142.49,192.168.142.50

keepalived架构

VIP:192.168.142.235
节点:192.168.142.48,192.168.142.49

搭建环境版本

数据库版本:5.7.18,5.7.18-log MySQL Community Server (GPL)
MHA版本:v0.58,mha4mysql-manager-0.58 + mha4mysql-node-0.58
Keepalived:keepalived-1.4.3
Linux主机:centos7.2

主机和安装服务列表

主机IP 安装服务
192.168.142.48 mysql master ; mha node ; keepalived
192.168.142.49 mysql slave ; mha node && mha manager ; keepalived
192.168.142.50 mysql slave ; mha node

搭建大体步骤

1、keepalived的搭建
2、linux机器之间配置互信
3、mysql主从环境的搭建
4、MHA的安装和配置
5、配置文件测试	
	测试ssh连通性
	测试集群中的主从复制
6、启动MHA管理节点

 

3. keepalived的搭建

这里使用rpm方式安装,分别在192.168.142.48和192.168.142.49上安装keepalived,也可使用源码编译

1、安装
yum install keepalived -y

2、配置文件修改
vim /etc/keepalived/keepalived.conf
! Configuration File for keepalived

global_defs {
   notification_email {
   root@localhost
}
   notification_email_from Alexandre.Cassen@firewall.loc
   smtp_server 127.0.0.1
   smtp_connect_timeout 30
   router_id LVS_DEVEL
}

vrrp_instance VI_1 {
    state MASTER
    interface eth0
    virtual_router_id 55
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        192.168.142.235
    }
}

note:其中主MASTER优先级高(100),BACKUP优先级(90)低一些

3、启动、关闭、查看
systemctl start keepalived
systemctl stop keepalived
systemctl status keepalived

 

4. linux机器之间配置互信

服务器之间建立ssh互信的方式很多,这里介绍一种私以为比较便捷的创建方式

1、创建秘钥(回车连续三次即可)
[root@192-168-142-48]# ssh-keygen -t rsa
2、进入.ssh目录查看文件
[root@192-168-142-48]# cd /root/.ssh/ && ls
id_rsa
id_rsa.pub
3、修改id_rsa.pub名称
mv id_rsa.pub authorized_keys
4、将/root/.ssh文件夹拷贝到192.168.142.49和192.168.142.50即可建立三台机器之间的互信(如果端口不是默认22,需要额外指定参数 -P port)
scp -P 8822 -r /root/.ssh 192.168.142.49:/root/
scp -P 8822 -r /root/.ssh 192.168.142.50:/root/

  

5. mysql主从环境的搭建

1、手动搭建或者自动化脚本分别在三台主机上配置mysql实例,这里可参考MySQL单实例搭建的方法,不在赘述

2、每台主机数据库实例上配置复制用户l和监控用户

1、复制用户
GRANT SUPER, REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'repl'@'192.168.142.%' IDENTIFIED BY '123456';FLUSH PRIVILEGES;
2、监控用户
GRANT ALL PRIVILEGES ON *.* TO 'root'@'192.168.142.%' IDENTIFIED BY '123456';FLUSH PRIVILEGES;

3、配置从同步

1、master上执行
show master status;,记录对应File名称和Position列的数字,这里为 mysql-bin.000001 154
2、slave1和slave2上分别执行
CHANGE MASTER TO MASTER_HOST='192.168.142.48',MASTER_USER='repl',MASTER_PASSWORD='123456',MASTER_PORT=5700,MASTER_LOG_FILE='mysql-bin.000001',MASTER_LOG_POS=154;

  

6. MHA的安装和配置

可参考官方文档详细介绍 https://github.com/yoshinorim/mha4mysql-manager/wiki/Installation   1、每台主机上安装node节点,这里使用rpm方式安装,也可使用源码编译

1、下载
https://github.com/yoshinorim/mha4mysql-node/releases  选择对应的rpm包下载
2、安装依赖
yum install perl-DBD-MySQL -y
3、安装node节点
rpm -ivh mha4mysql-node-0.58-0.el7.centos.noarch.rpm

  2、其中一台主机(192.168.142.49)安装manager节点即可,这里使用rpm方式安装,也可使用源码编译

1、下载
https://github.com/yoshinorim/mha4mysql-manager/releases  选择对应的rpm包下载
2、安装依赖
yum install perl-DBD-MySQL perl-Config-Tiny perl-Log-Dispatch perl-Parallel-ForkManager -y
3、安装manager节点
rpm -ivh mha4mysql-manager-0.58-0.el7.centos.noarch.rpm

   3、创建MHA的配置文件 app1.cnf,个人安装配置实例完整版已经放置到github,可参考查看,如下为链接 https://github.com/dwwang1992/configs-of-MHA/blob/master/app1.cnf    4、master_ip_failover_script对应的脚本 master_ip_failover,个人安装配置实例完整版已经放置到github,可参考查看,如下为链接 https://github.com/dwwang1992/configs-of-MHA/blob/master/master_ip_failover    5、master_ip_online_change_script对应的脚本 master_ip_online_change,个人安装配置实例完整版已经放置到github,可参考查看,如下为链接 https://github.com/dwwang1992/configs-of-MHA/blob/master/master_ip_online_change    6、report_script对应的脚本 send_report,个人安装配置实例完整版已经放置到github,可参考查看,如下为链接 https://github.com/dwwang1992/configs-of-MHA/blob/master/send_report  

7. 配置文件测试

测试ssh连通性

[root@hz-192-168-142-49 scripts]# masterha_check_ssh --conf=/data/mha/app1.cnf 
Fri May 25 14:24:34 2018 - [warning] Global configuration file /etc/masterha_default.cnf not found. Skipping.
Fri May 25 14:24:34 2018 - [info] Reading application default configuration from /data/mha/app1.cnf..
Fri May 25 14:24:34 2018 - [info] Reading server configuration from /data/mha/app1.cnf..
Fri May 25 14:24:34 2018 - [info] Starting SSH connection tests..
Fri May 25 14:24:37 2018 - [debug] 
Fri May 25 14:24:34 2018 - [debug]  Connecting via SSH from root@192.168.142.48(192.168.142.48:8822) to root@192.168.142.49(192.168.142.49:8822)..
Fri May 25 14:24:35 2018 - [debug]   ok.
Fri May 25 14:24:35 2018 - [debug]  Connecting via SSH from root@192.168.142.48(192.168.142.48:8822) to root@192.168.142.50(192.168.142.50:8822)..
Fri May 25 14:24:36 2018 - [debug]   ok.
Fri May 25 14:24:38 2018 - [debug] 
Fri May 25 14:24:35 2018 - [debug]  Connecting via SSH from root@192.168.142.49(192.168.142.49:8822) to root@192.168.142.48(192.168.142.48:8822)..
Fri May 25 14:24:35 2018 - [debug]   ok.
Fri May 25 14:24:35 2018 - [debug]  Connecting via SSH from root@192.168.142.49(192.168.142.49:8822) to root@192.168.142.50(192.168.142.50:8822)..
Fri May 25 14:24:37 2018 - [debug]   ok.
Fri May 25 14:24:39 2018 - [debug] 
Fri May 25 14:24:35 2018 - [debug]  Connecting via SSH from root@192.168.142.50(192.168.142.50:8822) to root@192.168.142.48(192.168.142.48:8822)..
Fri May 25 14:24:37 2018 - [debug]   ok.
Fri May 25 14:24:37 2018 - [debug]  Connecting via SSH from root@192.168.142.50(192.168.142.50:8822) to root@192.168.142.49(192.168.142.49:8822)..
Fri May 25 14:24:39 2018 - [debug]   ok.
Fri May 25 14:24:39 2018 - [info] All SSH connection tests passed successfully.

测试集群中的主从复制

[root@hz-192-168-142-49 scripts]# masterha_check_repl --conf=/data/mha/app1.cnf 
......
......
192.168.142.48(192.168.142.48:5700) (current master)
 +--192.168.142.49(192.168.142.49:5700)
 +--192.168.142.50(192.168.142.50:5700)

Fri May 25 14:25:57 2018 - [info] Checking replication health on 192.168.142.49..
Fri May 25 14:25:57 2018 - [info]  ok.
Fri May 25 14:25:57 2018 - [info] Checking replication health on 192.168.142.50..
Fri May 25 14:25:57 2018 - [info]  ok.
Fri May 25 14:25:57 2018 - [info] Checking master_ip_failover_script status:
Fri May 25 14:25:57 2018 - [info]   /data/mha/scripts/master_ip_failover --command=status --ssh_user=root --orig_master_host=192.168.142.48 --orig_master_ip=192.168.142.48 --orig_master_port=5700  --orig_master_ssh_port=8822
Unknown option: orig_master_ssh_port

IN SCRIPT TEST====systemctl stop keepalived==systemctl start keepalived===

Checking the Status of the script.. OK 
Fri May 25 14:25:57 2018 - [info]  OK.
Fri May 25 14:25:57 2018 - [warning] shutdown_script is not defined.
Fri May 25 14:25:57 2018 - [info] Got exit code 0 (Not master dead).

MySQL Replication Health is OK.

 

8. 启动MHA管理节点

启动命令

nohup masterha_manager --conf=/data/mha/app1.cnf --remove_dead_master_conf --ignore_last_failover < /dev/null > /data/mha/mha/app1/manager.log 2>&1 &
参数含义具体可参照官网说明  https://github.com/yoshinorim/mha4mysql-manager/wiki/masterha_manager,此处简单说明
--remove_dead_master_conf,发生failover后,MHA会自动从配置文件里移除dead master的相关信息
--ignore_last_failover,默认情况下,之前如果存在failover,那么再次启动MHA是不成功的,必须删除对应目录下的failover error文件, (manager_workdir)/(app_name).failover.error;设置此参数,就可以忽略上次是否错误而可以继续进行failover

关闭命令

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

查看状态

masterha_check_status --conf=/data/mha/app1.cnf

 

9. 在线手动切换过程

1、首先需要保证mha manager处于关闭状态

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

2、手动切换主master

masterha_master_switch --conf=/data/mha/app1.cnf --master_state=alive --new_master_host=192.168.142.48 --new_master_port=5700 --orig_master_is_new_slave --running_updates_limit=10000 --interactive=0
参数解释:
new_master_host:指定哪台成为新的主库
new_master_port:指定对应的数据库端口
orig_master_is_new_slave:将原来的主库变为从库
running_updates_limit:指定复制延迟在10000s内的都可切换
interactive:表示不需要人工干预,自动执行

3、切换过程

1、检查当前的配置信息及主从服务器的信息
			包括读取MHA的配置文件以及检查当前slave的健康状态
2、阻止对当前master的更新
			主要通过如下步骤:
			1> 等待1.5s($time_until_kill_threads*100ms),等待当前连接断开
			2> 执行 read_only=1,阻止新的DML操作
			3> 等待0.5s,等待当前DML操作完成
			4> kill掉所有连接
			5> FLUSH NO_WRITE_TO_BINLOG TABLES
			6> FLUSH TABLES WITH READ LOCK
3、等待新master执行完所有的relay log,执行完之后记录下对应的日志位点
			Waiting to execute all relay logs on 192.168.142.49(192.168.142.49:5700)..
			Getting new master's binlog name and position..
			mysql-bin.000001:2488
4、将新master的read_only设置为off,并添加VIP
5、slave切换到新master上
			1、等待slave应用完原主从复制产生的relay log,然后执行change master操作切换到新master上
			Waiting to execute all relay logs on 192.168.142.50(192.168.142.50:5700)..
			Resetting slave 192.168.142.50(192.168.142.50:5700) and starting replication from the new master 192.168.142.49(192.168.142.49:5700)..
			2、释放原master上的锁
			Unlocking all tables on the orig master:
			Executing UNLOCK TABLES..
			3、因masterha_master_switch命令行中带有--orig_master_is_new_slave参数,故原master也切换为新master的从
			Starting orig master as a new slave..
			Resetting slave 192.168.142.48(192.168.142.48:5700) and starting replication from the new master 192.168.142.49(192.168.142.49:5700)..
6、清理新master的相关信息
			192.168.142.49: Resetting slave info succeeded

  

10. 自动故障切换过程

1、首先需要保证mha manager处于运行状态

nohup masterha_manager --conf=/data/mha/app1.cnf --remove_dead_master_conf --ignore_last_failover < /dev/null > /data/mha/mha/app1/manager.log 2>&1 &

2、一旦主master出现宕机,会自动检测和选取新的主master

3、切换的过程

当master_manager监控到主库mysqld服务停止后,首先对主库进行SSH登录检查(save_binary_logs --command=test),然后对mysqld服务进行健康检查(PING(SELECT)每隔3秒检查一次,持续3次),参数secondary_check_script可用于double check,最后作出Master is down!的判断,master failover开始
1、先根据配置文件检测当前的复制环境中有哪些服务器,MHA也会校验诸如复制异常以及是否存在一些从库有不同的主库,启动failover(排除上次failover失败或者failover时间间隔太短)
 
2、隔离master server,把故障主库的VIP停掉(前提是你需要指定相关的脚本,比如:如果有master_ip_failover_script则会调用脚本停掉VIP、如果有shutdown_script脚本则调用脚本关闭master避免脑裂,具体在配置文件中app1.cnf)
  
3、选举新主库并尽量补全新主库的数据
			1、获取同步位置最靠前的从库:对比所有从库的master_log_file和read_master_log_pos位置找出执行位置最新和最旧的从库对应的故障主库的binlog位置
			2、保存dead master的binlog:在故障主库上执行save_binary_logs命令获得lastest slave同步位置与master间的binlog差异(使用3.1步骤找到的同步最靠前的从库binlog位置,如果故障主库系统没挂的情况下)并scp到mha manager server上
			scp from root@192.168.142.48:/data/mha/mha/tmp/saved_master_binlog_from_192.168.142.48_5700_20180525155119.binlog to local:/data/mha/mha/app1/saved_master_binlog_from_192.168.142.48_5700_20180525155119.binlog succeeded.
			3、确定和决定新的主库
			确定新的主库:先使用命令apply_diff_relay_logs --command=find把前面3.1步骤中找出的同步位置最靠前和最靠后的对应主库的binlog位置作为参数,在同步位置最靠前的从库上执行这个命令在其中继日志中找出两个binlog位置之间的relay log并生成文件用于恢复其他从库(这里就是检查同步最靠前的从库是否有从最老的位置开始的中继日志,这也是为什么MHA环境中执行过的中继日志不能删除的原因,否则这个对比就比较麻烦)
			接着寻找及决定新的主库,根据配置选择如何提升新主库(检查是否有设置candidate_master=1和no_master=1,如果有设置候选主库,那么候选主库中标,但候选库不一定就是有最新数据的slave,所以需要跟其他从库进行比较,当然如果候选主库恰好是同步位置最靠前的从库,就不需要跟其他从库进行relay log比较了;如果没有设置候选主库,那么同步位置最靠前的从库中标)。mha manager server也会将之前复制的差异binlog复制到新主库上
			4、新的主库应用日志(如果有任何错误从这个阶段会发生,需要手动恢复)
			新的主库首先需要对比master_log_file=relay_master_log_file,read_master_log_pos=exec_master_log_pos确认自己已经执行完成复制,如果新的主库不是同步位置最靠前的从库,那么需要使用apply_diff_relay_logs --command=generate_and_send命令比较自己和同步位置最靠前的从库之间的relay log是否存在差异,如果存在则需要生成一个差异relay log(如果新主库就是同步位置最靠前的从库,那么只需要执行mha manager server发过来的差异日志即可),然后使用这两个差异日志进行恢复数据(apply_diff_relay_logs --command=apply命令)。恢复完成后获取binlog位置并生成change master语句准备用于其他从库change master到新的主库上,并设置read_only=0。然后把VIP绑定到新的主库上。到这步骤新的主库切换完成
 
4、其他从库恢复:将其他从库数据尽量补全(所有从库并行执行)
并行使用apply_diff_relay_logs --command=generate_and_send命令判断各个从库的relay log位置和同步位置最靠前的从库之间的relay log差异,并把差异文件从同步位置最靠前的从库上发送到对应的各个从库上
并行使用两个差异日志进行恢复:mha manager server上的binlog差异拷贝到各个从库上,然后各个从库通过master_log_file=relay_master_log_file,read_master_log_pos=exec_master_log_pos先确认自己已经执行完成复制,再应用两个差异日志恢复数据。最后,执行reset slave,并重新CHANG MASTER到新主库上
  
5、清理新master的相关信息,到这里故障主库切换到新主库完成
			Resetting slave info on the new master..

 

11. 故障后的主机新加入资源组

第一种方法

1、vim /data/mha/app1.cnf 添加server1主机信息
[server1]
candidate_master=1
client_bindir=/usr/local/mysql-5.7.18/bin/
client_libdir=/usr/local/mysql-5.7.18/lib/
hostname=192.168.142.48
port=5700

2、将server1指向当前的master充当从的角色
CHANGE MASTER TO MASTER_HOST='192.168.142.49',MASTER_USER='repl',MASTER_PASSWORD='123456',MASTER_PORT=5700,MASTER_LOG_FILE='mysql-bin.000001',MASTER_LOG_POS=2488;

3、启动mha manager
nohup masterha_manager --conf=/data/mha/app1.cnf --remove_dead_master_conf --ignore_last_failover < /dev/null > /data/mha/mha/app1/manager.log 2>&1 &

  第二种方法

1、通过masterha_conf_host将server1主机信息添加进资源组
masterha_conf_host --command=add --conf=/data/mha/app1.cnf --block=server1 --hostname=192.168.142.48 --params="candidate_master=1;client_bindir=/usr/local/mysql-5.7.18/bin/;client_libdir=/usr/local/mysql-5.7.18/lib/;port=5700"
参数解释:
command:添加或者删除一个主机信息到配置文件
conf:配置文件的路径
hostname:主机信息ip
block:新添加的块名
params:额外参数列表,(key1=value1;key2=value2;...)

2、将server1指向当前的master充当从的角色
CHANGE MASTER TO MASTER_HOST='192.168.142.49',MASTER_USER='repl',MASTER_PASSWORD='123456',MASTER_PORT=5700,MASTER_LOG_FILE='mysql-bin.000001',MASTER_LOG_POS=2488;

3、启动mha manager
nohup masterha_manager --conf=/data/mha/app1.cnf --remove_dead_master_conf --ignore_last_failover < /dev/null > /data/mha/mha/app1/manager.log 2>&1 &

 

12. MHA 清理relay log(purge_relay_logs)

1、说明:

MySQL数据库主从复制在缺省情况下从库的relay logs会在SQL线程执行完毕后被自动删除
但是对于MHA场景下,对于某些滞后从库的恢复依赖于其他从库的relay log,因此采取禁用自动删除功能以及定期清理的办法
对于清理过多过大的relay log需要注意引起的复制延迟资源开销等。MHA可通过purge_relay_logs脚本及配合cronjob来完成此项任务

2、purge_relay_logs的功能

a、为relay日志创建硬链接(最小化批量删除大文件导致的性能问题)
b、SET GLOBAL relay_log_purge=1; FLUSH LOGS; SET GLOBAL relay_log_purge=0;
c、删除relay log(rm –f  /path/to/archive_dir/*)

3、purge_relay_logs的用法及相关参数

###用法
# purge_relay_logs --help
Usage:
    purge_relay_logs --user=root --password=rootpass --host=127.0.0.1

###参数描述
--user:mysql用户名,缺省为root
--password:mysql密码
--port:端口号
--host:主机名,缺省为127.0.0.1
--workdir:指定创建relay log的硬链接的位置,默认是/var/tmp,成功执行脚本后,硬链接的中继日志文件被删除由于系统不同分区创建硬链接文件会失败,故需要执行硬链接具体位置,建议指定为relay log相同的分区
--disable_relay_log_purge:默认情况下,参数relay_log_purge=1,脚本不做任何处理,自动退出,设定该参数,脚本会将relay_log_purge设置为0,当清理relay log之后,最后将参数设置为OFF(0)

4、定制清理relay log cronjob(每台主机均设置)

purge_relay_logs脚本在不阻塞SQL线程的情况下自动清理relay log。对于不断产生的relay log直接将该脚本部署到crontab以实现按天或按小时定期清理
1、编辑脚本,vim /data/mha/mha/purge_relay_logs.sh
#!/bin/bash
user=root
passwd=123456
port=5700
host=127.0.0.1
work_dir='/data/mha/mha/data'
purge='/bin/purge_relay_logs'
log_dir='/data/mha/mha/log'

if [ ! -d $log_dir ]
then
   mkdir $log_dir -p
fi

if [ ! -d $work_dir ]
then
   mkdir $work_dir -p
fi

$purge --user=$user --password=$passwd --port=$port --host=$host --workdir=$work_dir --disable_relay_log_purge >> $log_dir/purge_relay_logs.log 2>&1

2、最后添加到计划任务:
##每2天凌晨1点清空relay log
00 01 * * * /bin/bash /data/mha/mha/purge_relay_logs.sh