MHA简介

MHA (Master High Availability)是一套优秀的MySQL高可用性环境下故障切换和主从提升的高可用软件。在MySQL故障切换过程中,MHA能做到在0-30秒内自动完成数据库的故障切换,并且在进行故障切换的过程中,MHA能在最大程度上保证数据的一致性。

MHA由两部分组成:MHA Manager(管理节点)和MHA Node(数据节点)。MHA Manager可以单独部署在一台独立的机器上管理多个master-slave集群,也可以部署在一台slave节点上。MHA Node运行在每台MySQL服务器上,MHA Manager会定时参测集群中的master节点,当master出现故障时,它可以自动将最新数据的slave提升为新的master,然后将所有其它的slave重新指向新的master。整个故障转移过程对应用程序完全透明。

在MHA自动故障切换过程中,MHA试图从宕机的主服务器上保存二进制日志,最大程度的保证数据的不丢失,但并不总是可行的。例如主服务器硬件故障或无法通过ssh访问,MHA没法保存二进制日志,只进行故障转移而丢失了最新的数据。使用Mysql5.5的半同步复制,可以大大降低数据丢失的风险。MHA可以与半同步复制结合起来。如果只有一个slave已经收到了最新的二进制日志,MHA可以将最新的二进制日志应用于其他所有的slave服务器上,因此可以保证所有节点的数据一致性。

目前MHA主要支持一主多从的架构,要搭建MHA,要求一个复制集群中必须最少由3台数据库服务器,一主二从,即一台充当master,一台充当备用master,另外一台充当从库,因为至少需要3台服务器,出于机器成本的考虑,淘宝网也在该基础上进行了改造,目前淘宝TMHA已经支持一主一从。MHA适合任何存储引擎,只要能主从复制的存储引擎它都支持,不限于支持事务的innodb引擎。

MHA Manager管理多组主从复制。

mha部署架构 mha架构图_mha部署架构

MHA工作原理
1.从宕机崩溃的master保存二进制日志事件(binlog events)
2.识别含有最新更新的slave。
3.应用差异的中继日志(relay log)到其他的slave。
4.应用从master保存的二进制日志事件(binlog events)。
5.提升一个slave为新的master。
6.使其他的slave连接新的master进行复制。

MHA软件由两部分组成,Manager工具包和Node工具包,具体的说明如下。

Manager工具包
 masterha_check_ssh                #检查MHA的SSH配置状况
 masterha_check_repl                #检查Mysql的复制状况
 masterha_manager                   #启动MHA
 masterha_check_status            #检查当前MHA运行状态
 masterha_master_monitor       #检测master是否宕机
 masterha_master_switch         #控制故障转移
 masterha_conf_host                 #添加或删除配置的server信息Node工具包
 save_binary_logs                    #保存和复制master的二进制日志
 apply_diff_relay_logs              #识别差异的中继日志事件并将其差异的事件应用于其他的slave
 filter_mysqlbinlog                    #去除不必要的ROLLBACK事件(MHA已不在使用这个工具)
 purge_relay_logs                    #清除中继日志(不会阻塞SQL线程)

部署MHA

ip地址

主机名

角色

软件

192.168.0.60

centos-60

manager

mha4mysql-manag

mha4mysql-node

192.168.0.70

centos-70

master

mha4mysql-node

192.168.0.80

centos-80

slave1,Candidate master

mha4mysql-node

192.168.0.90

centos-90

slave2

mha4mysql-node

其中master对外提供写服务,备选Candidate master(slave1)提供读服务,slave2也提供读服务,一旦master宕机,将会把candidate master提升为新的master,slave指向新的master

配置所有节点的 ssh 免密码登录

ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa): #回车
Created directory '/root/.ssh'.
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.
[root@centos-60 ~]# ssh-copy-id 192.168.0.60
[root@centos-60 ~]# ssh-copy-id 192.168.0.70
[root@centos-60 ~]# ssh-copy-id 192.168.0.80
[root@centos-60 ~]# ssh-copy-id 192.168.0.90
[root@centos-70 ~]# ssh-keygen
[root@centos-70 ~]# ssh-copy-id 192.168.0.60
[root@centos-70 ~]# ssh-copy-id 192.168.0.70
[root@centos-70 ~]# ssh-copy-id 192.168.0.80
[root@centos-70 ~]# ssh-copy-id 192.168.0.90

 

[root@centos-80 ~]# ssh-keygen
[root@centos-80 ~]# ssh-copy-id 192.168.0.60
[root@centos-80 ~]# ssh-copy-id 192.168.0.70
[root@centos-80 ~]# ssh-copy-id 192.168.0.80
[root@centos-80 ~]# ssh-copy-id 192.168.0.90

 

[root@centos-90 ~]# ssh-keygen
[root@centos-90 ~]# ssh-copy-id 192.168.0.60
[root@centos-90 ~]# ssh-copy-id 192.168.0.70
[root@centos-90 ~]# ssh-copy-id 192.168.0.80
[root@centos-90 ~]# ssh-copy-id 192.168.0.90

安装mah-node 

所有节点安装mha-node


mha部署架构 mha架构图_mha部署架构_02


 鼠标左键点击

mha部署架构 mha架构图_centos_03

mha部署架构 mha架构图_mysql_04

这样勾选全部会话以后,在撰写栏输入的命令,敲击回车键后,所有标签都会执行。

yum install -y wget
wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
yum clean all
yum makecache
yum -y install perl-DBD-MySQL perl-Config-Tiny perl-Log-Dispatch perl-Parallel-ForkManager libappstream-glib deltarpm patchutils

上传 mha4mysql-node-0.57-0.el7.noarch.rpm 程序包到所有节点上
先上传到 centos-60上,然后复制到其他结点:

scp mha4mysql-node-0.57-0.el7.noarch.rpm 192.168.0.70:/root/
 scp mha4mysql-node-0.57-0.el7.noarch.rpm 192.168.0.80:/root/
 scp mha4mysql-node-0.57-0.el7.noarch.rpm 192.168.0.90:/root/


上传完后,所有节点,安装mha4mysql-node

rpm -ivh mha4mysql-node-0.57-0.el7.noarch.rpm

安装完后,会在/usr/bin/目录下生成一些脚本文件

mha部署架构 mha架构图_centos_05

安装MHA Manager

centos-60 执行安装Manager命令

yum -y install perl-DBD-MySQL perl-Config-Tiny perl-Log-Dispatch perl-Parallel-ForkManager perl-Time-HiRes perl-ExtUtils-CBuilder perl-ExtUtils-MakeMaker perl-CPAN
rpm -ivh mha4mysql-manager-0.57-0.el7.noarch.rpm

安装完成后会在/usr/bin 目录下面生成一些脚本文件 

 

mha部署架构 mha架构图_perl_06

配置Mysql主从 

centos-70  master
centos-80  slave,备用 master
centos-90  slave2

下载安装

链接:https://pan.baidu.com/s/1KZN47I63dBv510yHy5CRnA 
提取码:1234

rz 上传 mysql-5.7.tar.gz 到 192.168.0.70
 scp mysql-5.7.tar.gz 192.168.0.80:/root/
 scp mysql-5.7.tar.gz 192.168.1.90:/root/

主从库都安装mysql,设置密码

tar xvf mysql-5.7.tar.gz
 yum -y install ./mysql*.rpm
 systemctl start mysqld
 vim /etc/my.cnf
 validate-password=OFF
 systemctl restart mysqld
 grep 'password' /var/log/mysqld.log
 mysql -u root -p'buL.UJp!T2Od' 
 mysql> set password for root@localhost = password('123456');
 flush privileges;

配置主从

master库,centos-70创建要同步的数据

mysql> create database ha;
 mysql> use ha;
 mysql> create table test (id int,name varchar(20));
 mysql> insert into test value(1,'jack');
 mysql> exit配置 my.cnf
 [root@centos-70 ~]# vim /etc/my.cnf
 log-bin=mysql-bin-master
 server-id=1
 binlog-do-db=ha
 binlog-ignore-db=mysql

 重启服务
 systemctl restart mysqld && systemctl enable mysqld授权
 [root@centos-70 ~]# mysql -uroot -p123456
 mysql> grant replication slave on *.* to repl@'192.168.0.%' identified by '123456';
 mysql> flush privileges;查看状态信息:
 mysql> show master status;
 mysql> exit

mha部署架构 mha架构图_mha部署架构_07

将数据库上传到从节点
 [root@centos-70 ~]# mysqldump -uroot -p123456 -B ha>ha.sql
 [root@centos-70 ~]# scp ha.sql root@192.168.0.80:/root/
 [root@centos-70 ~]# scp ha.sql root@192.168.0.90:/root/

slave1库,centos-80配置为从节点

导入数据库
 [root@centos-80 ~]# mysql -uroot -p123456 < ha.sql

 配置 my.cnf
 [root@centos-80 ~]# vim /etc/my.cnf
 log-bin=mysql-bin-slave1
 server-id=2
 binlog-do-db=ha
 binlog-ignore-db=mysql
 log_slave_updates=1重启 MySQL 并授权
 [root@centos-80 ~]# systemctl restart mysqld && systemctl enable mysqld
 [root@centos-80 ~]# mysql -uroot -p123456
 mysql> grant replication slave on *.* to 'repl'@'192.168.0.%' identified by '123456';
 mysql> flush privileges;建立主从关系
 mysql> stop slave;
 mysql> change master to master_host='192.168.0.70',master_user='repl',master_password='123456';
 mysql> start slave;
 mysql> show slave status\G

mha部署架构 mha架构图_mha部署架构_08



slave2库,centos-90配置为从节点

导入数据库
 [root@centos-90 ~]# mysql -uroot -p123456 <ha.sql 配置 my.cnf:
 [root@centos-90 ~]# vim /etc/my.cnf
 log-bin=mysql-bin-slave2
 server-id=3
 binlog-do-db=ha
 binlog-ignore-db=mysql
 log_slave_updates=1  #只有开启 log_slave_updates,从库 binlog 才会记录主库同步的操作日志重启服务
 [root@centos-90 ~]# systemctl restart mysqld && systemctl enable mysqld授权
 [root@centos-90 ~]# mysql -uroot -p123456
 mysql> grant replication slave on *.* to 'repl'@'192.168.0.%' identified by '123456';
 mysql> flush privileges;建立主从关系
 mysql> stop slave;
 mysql> change master to master_host='192.168.0.70',master_user='repl',master_password='123456';
 mysql> start slave;
 mysql> show slave status\G

mha部署架构 mha架构图_centos_09

测试主从同步
 [root@centos-70 ~]# mysql -uroot -p123456
 mysql> insert into ha.test values(2,'zhaoyun');mysql> select * from ha.test;

mha部署架构 mha架构图_mha部署架构_10

mysql> select * from ha.test;

mha部署架构 mha架构图_mysql_11

配置 MHA 管理用户

两台 slave 服务器设置 read_only(从库对外提供读服务,不要写进配置文件,当集群发生切换时新的 master 节点会取消只读状态)

[root@centos-80 ~]# mysql -u root -p123456 -e 'set global read_only=1'
继续设置centos-90
[root@centos-90 ~]# mysql -u root -p123456 -e 'set global read_only=1'
mysql> show variables like '%read_only%';
 mysql> set global read_only=1;

设置为1就是ON,设置为0就是OFF,进行主备切换的时候,一般都会先对主库进行只读操作(on),然后主备同步完成后,再把备库置为可读写(off)。这样可以避免切换的过程中双写引起脏数据。

mha部署架构 mha架构图_mysql_12

在所有数据库结点上创建 mha 管理用户
远程登录用户必须拥有 localhost 权限才可以登录,必须先授权 localhost 再授权 192.168.1.%

[root@centos-70 ~]# mysql -u root -p123456
 mysql> grant all privileges on *.* to 'mha'@'localhost' identified by '123456';
 mysql> grant all privileges on *.* to 'mha'@'192.168.0.%' identified by '123456';
 mysql> flush privileges;
 [root@centos-80 ~]# 同上
 [root@centos-90 ~]# 同上

到这里整个集群环境已经搭建完毕,剩下的就是配置 MHA 软件了。

配置 MHA

创建 MHA 的工作目录,并且创建相关配置文件

[root@centos-60 ~]# mkdir -p /etc/masterha
 [root@centos-60 ~]# mkdir -p /var/log/masterha/app1
 [root@centos-60 ~]# cd /etc/masterha/
 [root@centos-60 masterha]# vim /etc/masterha/app1.cnf

mha部署架构 mha架构图_mha部署架构_13

 

[server default]
manager_workdir=/var/log/masterha/app1
manager_log=/var/log/masterha/app1/manager.log
master_binlog_dir=/var/lib/mysql
master_ip_failover_script=/usr/local/bin/master_ip_failover
password=123456
user=mha
ping_interval=1
remote_workdir=/tmp
repl_password=123456
repl_user=repl
ssh_user=root

[server1]
hostname=192.168.0.70
port=3306

[server2]
hostname=192.168.0.80
port=3306
candidate_master=1
check_repl_delay=0

[server3]
hostname=192.168.0.90
port=3306

上传 master_ip_failover 脚本文件到主机上/usr/local/bin/目录下,MHA 主程序负责对数据转移和故障切换功能,该脚本负责对 VIP 进行切换
[root@centos7-60 ~]# mv master_ip_failover /usr/local/bin/
[root@centos7-60 ~]# chmod +x /usr/local/bin/master_ip_failover 
[root@centos7-60 bin]# vim /usr/local/bin/master_ip_failover
修改ip为192.168.0.66当作虚拟IP,修改网卡名为当前主机网卡名,这样web应用使用的是192.168.0.66这个虚拟IP,也就是vip,如果当前主机宕机,这个vip就会漂移到新的可用主机上(也就是新的master上)

mha部署架构 mha架构图_centos_14

关闭 relay log 的自动清除功能(在每个 slave 节点上)

mha部署架构 mha架构图_mysql_15

[root@centos-80 ~]# mysql -uroot -p123456 -e 'set global relay_log_purge=0'
[root@centos-90 ~]# mysql -uroot -p123456 -e 'set global relay_log_purge=0'

MHA 在发生切换的过程中,从库的恢复过程中依赖于 relay log 的相关信息,所以这里要将 relay log的自动清除设置为 OFF,采用手动清除 relay log 的方式。在默认情况下,从服务器上的中继日志会在 SQL线程执行完毕后被自动删除。但是在 MHA 环境中,这些中继日志在恢复其他从服务器时可能会被用到,因此需要禁用中继日志的自动删除功能

手动清除 relay log 的方式
show relaylog events;
1、stop slave;
reset slave;
show relaylog events;
Empty set (0.00 sec)
2、只有装上 mha-node 才可以用下面方式
purge_relay_logs --user=mha --password=123456 --disable_relay_log_purge

MHA 配置检查

 

检查 SSH 配置

[root@centos7-60 ~]# masterha_check_ssh --conf=/etc/masterha/app1.cnf

mha部署架构 mha架构图_mha部署架构_16

检查整个 mysql 主从复制状态

[root@centos7-60 ~]# masterha_check_repl --conf=/etc/masterha/app1.cnf

这个检查有可能is not ok,再重新检查一次

mha部署架构 mha架构图_perl_17

开启 MHA Manager 监控

[root@centos7-60 ~]# nohup masterha_manager --conf=/etc/masterha/app1.cnf --remove_dead_master_conf --ignore_last_failover < /dev/null > /var/log/masterha/app1/manager.log 2>&1 &

--remove_dead_master_conf #该参数代表当发生主从切换后,老的主库的 IP 将会从配置文件中移除。 
--manger_log #日志存放位置
--ignore_last_failover #我需要忽略上次故障转移。默认情况,如果先前的故障转移失败,则 MHA 不会启动故障转移,因为该问题可能再次发生。

检查 MHA Manager 的状态

[root@centos7-60 ~]# masterha_check_status --conf=/etc/masterha/app1.cnf

mha部署架构 mha架构图_mysql_18


正常,会显示"PING_OK",否则会显示"NOT_RUNNING",这代表 MHA 监控没有开启。

查看启动日志

[root@centos7-60 ~]#  tail -n20 /var/log/masterha/app1/manager.log

mha部署架构 mha架构图_centos_19

关闭 MHA Manage 监控的方法,这里不需要执行此语句。
[root@centos7-60 ~]# masterha_stop --conf=/etc/masterha/app1.cnf

进行测试

启动MHA 

[root@centos7-60 ~]# nohup masterha_manager --conf=/etc/masterha/app1.cnf --remove_dead_master_conf --ignore_last_failover < /dev/null > /var/log/masterha/app1/manager.log 2>&1 &

主master停止服务

[root@centos-70 ~]# systemctl stop mysqld
 manager进行日志监控
 [root@centos7-60 ~]# tail -f /var/log/masterha/app1/manager.log

mha部署架构 mha架构图_centos_20

已经切换成功,切换为192.168.0.80
进入centos-90查看,show slave status\G 已经切换

mha部署架构 mha架构图_mysql_21

centos-80执行以下命令

insert into ha.test values(3,'test');

centos-90执行以下命令

select * from ha.test;

查看是否同步80的数据

centos-80切换为主后,read_only 自动关闭

mha部署架构 mha架构图_perl_22


mha部署架构 mha架构图_perl_23

可以看到出错的server1主库已经从配置文件中被移除

mha部署架构 mha架构图_centos_24


再次检查状态,MHA manager已经停止运行了

mha部署架构 mha架构图_mysql_25

让被关闭的故障主机重新加入

[root@centos-70 ~]# systemctl start mysqld

[root@centos-70 ~]# mysql -uroot -p123456 -e 'set global read_only=ON'

[root@centos-70 ~]# mysql -uroot -p123456 -e 'set global relay_log_purge=OFF'

mysql -uroot -p123456

select * from ha.test;

查看下当前数据,发现centos-80新增的数据还没有同步过来。

mha部署架构 mha架构图_centos_26


stop slave;

mysql> change master to master_host='192.168.0.80',master_user='repl',master_password='123456';

flush privileges;

这里因为你现在已经是从了,不是主了,所以要重新设定主从关系。

mysql> start slave;

mysql> show slave status\G

mha部署架构 mha架构图_centos_27

select * from ha.test;

查看70宕机后,80新增的数据是否同步过来,数据是否一致。已经同步过来,数据一致。

mha部署架构 mha架构图_perl_28

[root@centos7-60 bin]# vim /etc/masterha/app1.cnf

mha部署架构 mha架构图_mysql_29

重新添加[server1],并且设置为后背主,把[server2]的后背主设定删除。
[root@centos7-60 bin]# masterha_check_repl --conf=/etc/masterha/app1.cnf

mha部署架构 mha架构图_centos_30

进行检查,发现80为当前的主,而70变为了从,小弟变大哥,大哥变小弟了。

启动MHA 

[root@centos7-60 ~]# nohup masterha_manager --conf=/etc/masterha/app1.cnf --remove_dead_master_conf --ignore_last_failover < /dev/null > /var/log/masterha/app1/manager.log 2>&1 &

 

检查运行状态

[root@centos7-60 ~]# masterha_check_status --conf=/etc/masterha/app1.cnf

mha部署架构 mha架构图_mha部署架构_31


[root@centos7-60 ~]# tail -f /var/log/masterha/app1/manager.log

mha部署架构 mha架构图_mha部署架构_32

Ping(SELECT)成功,等待中,直到MySQL没有响应。 
 

centos80进行停止服务。

[root@centos-80 ~]# systemctl stop mysqld

centos90查看日志,是否切换到70

[root@centos-90 ~]#show slave status\G

mha部署架构 mha架构图_perl_33

70执行以下命令

select * from ha.test; 查看数据和90的数据是否一致。

insert into ha.test values (4,'abc');

exit

ip a

查看虚拟ip是否为192.168.0.66

mha部署架构 mha架构图_perl_34


90执行以下命令

select * from ha.test; 查看数据是否和70一致。结果数据一致。

mha部署架构 mha架构图_mysql_35