一、 MHA概述

  1. 概念
    MHA(Master High Availability)事由日本人DeNA开发的一套MySQL高可用性环境下故障切换和主从提升的软件,目前在MySQL高可用方面是一个相对成熟的解决方案。在MySQL故障切换过程中,MHA能做到在0~30秒之内自动完成数据库的故障切换操作,并且在进行故障切换的过程中,MHA能在最大程度上保证数据的一致性,以达到真正意义上的高可用。
  2. MHA的主要功能
  • 自动故障检测和自动故障转移
  • 交互式(手动)故障转移
  • 在线切换Master到不同的主机
  1. MHA的优势
  • 自动故障转移快
  • 主库崩溃不存在数据一致性问题
  • 配置不需要对当前mysql环境做重大修改
  • 不需要添加额外的服务器(仅一台manager就可管理上百个replication)
  • 性能优秀,可工作在半同步复制和异步复制
  • 只要replication支持的存储引擎,MHA都支持,不会局限于innodb
  1. MHA的组成部分

MHA由Manager节点和Node节点组成;MHA Manager可以单独部署在一台独立的机器上管理多个master-slave集群,也可以部署在一台slave节点上。MHA Node运行在每台MySQL服务器上。

  1. MHA工作原理
  • MHA Manager会定时探测集群中的master节点
  • 当master出现故障时,从宕机崩溃的master保存二进制日志事件(binlog events);
  • 识别含有最新更新的slave;
  • 应用差异的中继日志(relay log)到其他的slave;
  • 应用从master保存的二进制日志事件(binlog events);
  • 提升一个slave为新的master,使其他的slave连接新的master进行复制;

二、MHA部署

  1. 服务器规划

主机名

IP地址

节点信息

数据库版本

系统版本

manager

192.168.1.112

mha manager

Centos 7.4.1708

mysql01

192.168.1.103

mysql主节点

mysql 5.7.25

Centos 7.4.1708

mysql02

192.168.1.111

mysql从节点

mysql 5.7.25

Centos 7.4.1708

mysql03

192.168.1.127

mysql从节点

mysql 5.7.25

Centos 7.4.1708

  1. 拓扑结构

MHA缺点 mysql mysql的mha高可用原理_MHA

  1. 三个mysql节点上安装mysql 5.7

(1)安装数据库

#  wget http://dev.mysql.com/get/mysql57-community-release-el7-10.noarch.rpm
 #  yum -y install mysql57-community-release-el7-10.noarch.rpm
 #  yum -y install mysql-community-server

(2)修改初始密码

安装完成后改密码  
[root@mysql02 ~]# cat /var/log/mysqld.log | grep password
2019-03-04T14:04:44.194031Z 1 [Note] A temporary password is generated for root@localhost: qId8M?Arkglb
[root@mysql02 ~]# mysql -u root -p'qId8M?Arkglb'

这个时候你会发现如果设置成123456 显然不成功,因为mysql5.7 设置有密码安全机制,不可以设置成肩带的密码,如下图所示

MHA缺点 mysql mysql的mha高可用原理_perl_02


默认是1,即MEDIUM,所以刚开始设置的密码必须符合长度,且必须含有数字,小写或大写字母,特殊字符。有时候,只是为了自己测试,不想密码设置得那么复杂,譬如说,我只想设置root的密码为123456。

必须修改两个全局参数:

mysql> set global validate_password_policy=0;
Query OK, 0 rows affected (0.00 sec)

密码默认长度为8  改为1
mysql> set global validate_password_length=1;
Query OK, 0 rows affected (0.00 sec)

sql> alter user 'root'@'localhost' identified by '123456';
Query OK, 0 rows affected (0.01 sec)

(3)mysql节点1 创建数据库 用于之后备份数据

mysql> create database course;
Query OK, 1 row affected (0.01 sec)
mysql> create table one(id int);
Query OK, 1 row affected (0.01 sec)

mysqldump -uroot -p course > /root/course.sql
scp /root/course.sql mysql02:/root
scp /root/course.sql mysql03:/root
  1. 编辑hosts文件 并传输给其他节点
manager节点编辑并传给其他节点

 vim /etc/hosts
      192.168.1.112 manager
      192.168.1.103 mysql01
      192.168.1.111 mysql02
      192.168.1.127 mysql03

scp /etc/hosts mysql01:/etc/
scp /etc/hosts mysql02:/etc/
scp /etc/hosts mysql03:/etc/
  1. 做免密登录

由于MHA manager通过SSH访问所有的node节点,各个node节点也同样通过SSH来相互发送不同的relay log 文件,所以要在每一个node和manager上配置SSH无密码登陆。
每个节点都生成密钥对,并把公钥传给其他三台主机

manager主机的操作

   20  ssh-keygen
   21  ssh-copy-id -i /root/.ssh/id_rsa.pub mysql01
   22  ssh-copy-id -i /root/.ssh/id_rsa.pub mysql02
   23  ssh-copy-id -i /root/.ssh/id_rsa.pub mysql03

其他三台主机操作类似,自己操作即可,不再演示
  1. 配置mysql主从环境

(1)mysql主节点配置

[mysqld]
log-bin=mysql-bin
server-id=1
binlog-do-db=course
binlog-ignore-db=mysql
character-set-server=utf8
init_connect='SET AUTOCOMMIT=0;set names utf8' #设置客户端不自动提交事务(需手动提交)  且字符集为utf8
gtid_mode = on
enforce_gtid_consistency = 1
log_slave_updates = 1
plugin_load = "rpl_semi_sync_master=semisync_master.so;rpl_semi_sync_slave=semisync_slave.so"
loose_rpl_semi_sync_master_enabled = 1
loose_rpl_semi_sync_slave_enabled = 1
loose_rpl_semi_sync_master_timeout = 5000  #半同步复制的超时时间

关于配置的说明

GTID是MySQL 5.6的新特性,其全称是Global Transaction Identifier,可简化MySQL的主从切换以及Failover。GTID用于在binlog中唯一标识一个事务。当事务提交时,MySQL Server在写binlog的时候,会先写一个特殊的Binlog Event,类型为GTID_Event,指定下一个事务的GTID,然后再写事务的Binlog。主从同步时GTID_Event和事务的Binlog都会传递到从库,从库在执行的时候也是用同样的GTID写binlog,这样主从同步以后,就可通过GTID确定从库同步到的位置了。也就是说,无论是级联情况,还是一主多从情况,都可以通过GTID自动找点儿,而无需像之前那样通过File_name和File_position找点儿了。

log_slave_updates=1 
该选项告诉从服务器将其SQL线程执行的更新记入到从服务器自己的二进制日志

最后几项为开启mysql半同步复制

异步复制(Asynchronous replication)
MySQL默认的复制即是异步的,主库在执行完客户端提交的事务后会立即将结果返给给客户端,并不关心从库是否已经接收并处理,这样就会有一个问题,主如果crash掉了,此时主上已经提交的事务可能并没有传到从上,如果此时,强行将从提升为主,可能导致新主上的数据不完整。

全同步复制(Fully synchronous replication)
指当主库执行完一个事务,所有的从库都执行了该事务才返回给客户端。因为需要等待所有从库执行完该事务才能返回,所以全同步复制的性能必然会收到严重的影响。

半同步复制(Semisynchronous replication)
介于异步复制和全同步复制之间,主库在执行完客户端提交的事务后不是立刻返回给客户端,而是等待至少一个从库接收到并写到relay log中才返回给客户端。相对于异步复制,半同步复制提高了数据的安全性,同时它也造成了一定程度的延迟,这个延迟最少是一个TCP/IP往返的时间。所以,半同步复制最好在低延时的网络中使用。

(2)两台从节点的配置如下

[mysqld]
log-bin=mysql-bin
server-id=2
binlog-do-db=course
binlog-ignore-db=mysql
character-set-server=utf8
init_connect='SET AUTOCOMMIT=0;set names utf8'
gtid_mode = on
enforce_gtid_consistency = 1
log_slave_updates = 1
plugin_load = "rpl_semi_sync_master=semisync_master.so;rpl_semi_sync_slave=semisync_slave.so"
loose_rpl_semi_sync_master_enabled = 1
loose_rpl_semi_sync_slave_enabled = 1
loose_rpl_semi_sync_master_timeout = 5000


mysql> create database course;
Query OK, 1 row affected (0.11 sec)

mysql> use course
Database changed

mysql> source /root/course.sql

(3)同步数据
获取主库的bin log信息 并备份主库

mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000005 |      154 |              |                  |                   |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)

在从库上导入数据并开启主从复制

mysql> stop slave;

mysql> change master to
    -> master_host='192.168.1.103',
    -> master_user='repl',
    -> master_password='replication',
    -> master_port=3306,
    -> master_log_file='mysql-bin.000005',
    -> master_log_pos=154;
Query OK, 0 rows affected, 2 warnings (0.10 sec)

mysql> start slave;
Query OK, 0 rows affected (0.00 sec)

(4)创建数据同步用户和监控用户,三台数据库都执行

grant replication slave on *.* to 'repl'@'192.168.1.%' identified by '123456';
 grant all privileges on *.* to 'root'@'192.168.1.%' identified  by '123456';
  1. 安装MHA

(0) 安装依赖环境

yum install perl-DBD-MySQL perl-Config-Tiny perl-Log-Dispatch perl-Parallel-ForkManager perl-ExtUtils-CBuilder perl-ExtUtils-MakeMaker perl-CPAN

yum -y install 'perl(Module::Install)'

(1) 在各节点上安装mha4mysql-node

mha4mysql-node下载地址:https://github.com/yoshinorim/mha4mysql-node/releases/tag/v0.58

mha4mysql-manager下载地址:https://github.com/yoshinorim/mha4mysql-manager/releases/tag/v0.58

tar xf mha4mysql-node-0.57.tar.gz
cd mha4mysql-node-0.57
perl Makefile.PL
make && make install

(2) 在管理节点上安装manager

tar xf mha4mysql-manager-0.57.tar.gz 
cd mha4mysql-manager-0.57
perl Makefile.PL
make && make install

(3)manager管理工具

在manager节点安装完成后会生成一些管理工具,manager的主要管理工具有:

masterha_check_ssh:检查MHA的SSH配置状况
masterha_check_repl:检查MySQL复制状况
masterha_manger:启动MHA
masterha_check_status:检测当前MHA运行状态
masterha_master_monitor:检测master是否宕机
masterha_master_switch:控制故障转移(自动或者手动)
masterha_conf_host:添加或删除配置的server信息

(4)管理节点工具包

save_binary_logs                保存和复制master的二进制日志
apply_diff_relay_logs           识别差异的中继日志事件并将其差异的事件应用于其他的slave
filter_mysqlbinlog              去除不必要的ROLLBACK事件(MHA已不再使用这个工具)
purge_relay_logs                清除中继日志(不会阻塞SQL线程)
  1. 配置MHA

(1)MHA管理端和客户端安装完成后,在管理端需要创建MHA的配置文件,配置文件内容如下:

cp /root/mha4mysql-manager-0.58/samples/conf/masterha_default.cnf /etc
/etc/masterha_default.cnf文件的修改可以参照app1.cnf中default server部分进行修改

cp -ra /root/mha4mysql-manager-0.58/samples/scripts/* /usr/local/bin/

master_ip_failover     #自动切换时vip管理的脚本,不是必须,如果我们使用keepalived的,我们可以自己编写脚本完成对vip的管理,比如监控mysql,如果mysql异常,我们停止keepalived就行,这样vip就会自动漂移
master_ip_online_change    #在线切换时vip的管理,不是必须,同样可以可以自行编写简单的shell完成
power_manager     #故障发生后关闭主机的脚本,不是必须
send_report       #因故障切换后发送报警的脚本,不是必须,可自行编写简单的shell完成。

mkdir -p /etc/masterha
mkdir /var/log/masterha/app1
cp /root/mha4mysql-manager-0.57/samples/conf/app1.cnf /etc/masterha/
vim /etc/masterha/app1.cnf

[server default]
manager_workdir=/var/log/masterha/app1
manager_log=/var/log/masterha/app1/manager.log
master_binlog_dir=/var/log
master_ip_failover_script= /usr/local/bin/master_ip_failover
master_ip_online_change_script= /usr/local/bin/master_ip_online_change
password=123456
user=root
ping_interval=1
remote_workdir=/tmp
repl_password=123456
repl_user=repl
report_script=/usr/local/send_report
secondary_check_script= /usr/local/bin/masterha_secondary_check -s 192.168.1.132 -s 192.168.1.177
shutdown_script=""
ssh_user=root

[server1]
hostname=192.168.1.167
port=3306


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


[server3]
port=3306
hostname=192.168.1.177

(2)MHA主要配置文件说明

secondary_check_script //
一般来说,它是强烈建议有两个或多个网络线路检查MySQL主服务器的可用性。默认情况下,只有单一的路线 MHA Manager检查:从Manager to Master。但这是不可取的。MHA实际上可以有两个或两个以上的检查路线通过调用外部脚本定义二次检查脚本参数
shutdown_script=""      //设置故障发生后关闭故障主机脚本(该脚本的主要作用是关闭主机放在发生脑裂,这里没有使用)

candidate_master=1:设置为候选master,如果设置该参数以后,发生主从切换以后将会将此从库提升为主库,即使这个主库不是集群中事件最新的slave

check_repl_delay=0   //默认情况下如果一个slave落后master 100M的relay logs的话,MHA将不会选择该slave作为一个新的master,因为对于这个slave的恢复需要花费很长时间,通过设置check_repl_delay=0,MHA触发切换在选择一个新的master的时候将会忽略复制延时,这个参数对于设置了candidate_master=1的主机非常有用,因为这个候选主在切换的过程中一定是新的master

(3)修改/usr/local/bin/master_ip_failover,这里使用脚本管理vip

vim /usr/local/bin/master_ip_failover

#!/usr/bin/env perl

use 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 = '192.168.1.188/24';  #此处为你要设置的虚拟ip
my $key = '1';
my $ssh_start_vip = "/usr/sbin/ifconfig ens32:$key $vip"; #此处改为你的网卡名称
my $ssh_stop_vip = "/usr/sbin/ifconfig ens32:$key down";

在文件最后的sub useage{} 上添加内容

sub start_vip() {
    `/usr/bin/ssh  $ssh_user\@$new_master_host \" $ssh_start_vip \"`;
}
sub stop_vip() {
     return 0  unless  ($ssh_user);
    `/usr/bin/ssh  $ssh_user\@$orig_master_host \" $ssh_stop_vip \"`;
}


 注释 掉这一行 FIXME_xxx;
  1. 检查MHA的环境是否工作正常

(1)通过masterha_check_ssh脚本检测SSH连接是否配置正常

[root@localhost ~]#  masterha_check_ssh --conf=/etc/manager.cnf
Warning: Permanently added '192.168.1.176' (ECDSA) to the list of known hosts.
Wed Mar  6 15:34:28 2019 - [debug]   ok.
Wed Mar  6 15:34:29 2019 - [info] All SSH connection tests passed successfully.

(2)在管理节点检查复制配置

为了让MHA正常工作,所有的master和slave必须在配置文件中正确配置,MHA可通过masterha_check_repl 脚本检测复制是否正确配置。

[root@localhost etc]# masterha_check_repl --conf=/etc/masterha/app1.cnf

Sun Mar 10 16:47:58 2019 - [info] 
192.168.1.167(192.168.1.167:3306) (current master)
 +--192.168.1.132(192.168.1.132:3306)
 +--192.168.1.177(192.168.1.177:3306)

Checking the Status of the script.. OK 
Sun Mar 10 16:47:58 2019 - [info]  OK.
Sun Mar 10 16:47:58 2019 - [warning] shutdown_script is not defined.
Sun Mar 10 16:47:58 2019 - [info] Got exit code 0 (Not master dead).

MySQL Replication Health is OK.

(3)检查MHA状态

masterha_check_status --conf=/etc/masterha/app1.cnf

(4)启动MHA
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检测到连续发生宕机,且两次宕机间隔不足8小时的话,则不会进行

Failover,之所以这样限制是为了避免ping-pong效应。该参数代表忽略上次MHA触发切换产生的文件,默认情况下,

MHA发生切换后会在日志目录,也就是上面我设置的/data产生app1.failover.complete文件,下次再次切换的时候

如果发现该目录下存在该文件将不允许触发切换,除非在第一次切换后收到删除该文件,为了方便,这里设置

为--ignore_last_failover。

(5)停止MHA

masterha_stop –conf=/etc/masterha/app1.cnf

(6)检查MHA启动状态

[root@localhost etc]# tail /var/log/masterha/app1/manager.log 

IN SCRIPT TEST====/usr/sbin/ifconfig ens32:2 down==/usr/sbin/ifconfig ens32:2 192.168.1.188/24===

Checking the Status of the script.. OK 
Sun Mar 10 16:55:32 2019 - [info]  OK.
Sun Mar 10 16:55:32 2019 - [warning] shutdown_script is not defined.
Sun Mar 10 16:55:32 2019 - [info] Set master ping interval 1 seconds.
Sun Mar 10 16:55:32 2019 - [info] Set secondary check script: /usr/local/bin/masterha_secondary_check -s 192.168.1.132 -s 192.168.1.177
Sun Mar 10 16:55:32 2019 - [info] Starting ping health check on 192.168.1.167(192.168.1.167:3306)..
Sun Mar 10 16:55:32 2019 - [info] Ping(SELECT) succeeded, waiting until MySQL doesn't respond..

如上表示启动成功

(7)使用 ip a 可以在mysql主库上看到设置的漂移ip,杀死master后,slave1和slave2成为主从结构

----- Failover Report -----

app1: MySQL Master failover 192.168.1.167(192.168.1.167:3306) to 192.168.1.132(192.168.1.132:3306) succeeded

Master 192.168.1.167(192.168.1.167:3306) is down!

Check MHA Manager logs at manager:/var/log/masterha/app1/manager.log for details.

Started automated(non-interactive) failover.
Invalidated master IP address on 192.168.1.167(192.168.1.167:3306)
Selected 192.168.1.132(192.168.1.132:3306) as a new master.
192.168.1.132(192.168.1.132:3306): OK: Applying all logs succeeded.
192.168.1.132(192.168.1.132:3306): OK: Activated master IP address.
192.168.1.177(192.168.1.177:3306): OK: Slave started, replicating from 192.168.1.132(192.168.1.132:3306)
192.168.1.132(192.168.1.132:3306): Resetting slave info succeeded.
Master failover to 192.168.1.132(192.168.1.132:3306) completed successfully.
Sun Mar 10 17:24:59 2019 - [info] Sending mail..
sh: /usr/local/send_report: No such file or directory
Sun Mar 10 17:24:59 2019 - [error][/usr/local/share/perl5/MHA/MasterFailover.pm, ln2089] Failed to send mail with return code 127:0

在新的主库上查看ip地址 也可以看得到漂移ip188 如下

ens32: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 00:0c:29:32:26:97 brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.132/24 brd 192.168.1.255 scope global dynamic ens32
       valid_lft 65194sec preferred_lft 65194sec
    inet 192.168.1.188/24 brd 192.168.1.255 scope global secondary ens32:2
       valid_lft forever preferred_lft forever
    inet6 fe80::20c:29ff:fe32:2697/64 scope link 
       valid_lft forever preferred_lft forever

旧的master修复之可以继续当做从库使用,只需要在旧的master执行以下命令

stop slave;

CHANGE MASTER TO MASTER_HOST='192.168.1.132', MASTER_PORT=3306, MASTER_AUTO_POSITION=1, MASTER_USER='repl', MASTER_PASSWORD='123456';

start slave;

show slave status\G

(8)特殊情况下也可以手动切换主

masterha_master_switch --master_state=dead --conf=/etc/masterha/app1.cnf --dead_master_host=192.168.1.167 --dead_master_port=3306 --new_master_host=192.168.1.132 --new_master_port=3306 --ignore_last_failover

MHA配置文件中所有参数的详细文档请参考
https://github.com/yoshinorim/mha4mysql-manager/wiki/Parameters