《一文搞定 MHA 高可用!MySQL 主从集群故障自动切换 + 数据一致性保障方案》

MHA高可用架构

1. 介绍

MHA(Master HA)是一款开源的 MySQL 的高可用程序,它为 MySQL 主从复制架构提供了automating master failover 功能。MHA 在监控到 master 节点故障时,会提升其中拥有最新数据的slave 节点成为新的master 节点,在此期间,MHA 会通过其它从节点获取额外信息来避免一致性方面的问题。MHA 还提供了 master 节点的在线切换功能,即按需切换 master/slave 节点。
MHA 是由日本人 yoshinorim(原就职于DeNA现就职于FaceBook)开发的比较成熟的 MySQL 高可用方案。MHA 能够在30秒内实现故障切换,并能在故障切换中,最大可能的保证数据一致性。

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

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

2. 工作原理

MHA工作原理:

  • 目前MHA主要支持一主多从的架构,要搭建MHA,要求一个复制集群必须最少有3台数据库服务器,一主二从,即一台充当Master,一台充当备用Master,一台充当从库。

  • MHA Node 运行在每台 MySQL 服务器上。

  • MHAManager 会定时探测集群中的master 节点。

  • 当master 出现故障时,它可以自动将最新数据的slave 提升为新的master

  • 然后将所有其他的slave 重新指向新的master,VIP自动漂移到新的master。

  • 整个故障转移过程对应用程序完全透明。

3. 环境说明 (实验中主机mha就是mha-manager主机)

机器名称IP配置操作系统版本/数据库版本说明
mha-manager192.168.168.200rhel7.9manager控制器
master192.168.168.128rhel7.9/mysql8.0.40数据库主服务器
rep1192.168.168.129rhel7.9/mysql8.0.40数据库从服务器
rep2192.168.168.130rhel7.9/mysql8.0.40数据库从服务器

4. 准备工作

4.1 初始化主节点master的配置:

[root@master ~]# cat /etc/my.cnf
[mysqld]
datadir=/data/mysql
socket=/data/mysql/mysql.sock
server_id=128
gtid_mode=ON
enforce_gtid_consistency=ON
log-bin=binlog
relay-log=relay-log
relay_log_purge=0
log-slave-updates=true

4.2 初始化rep1和rep2节点:

#rep1
[root@rep1 ~]# cat /etc/my.cnf
[mysqld]
datadir=/data/mysql
socket=/data/mysql/mysql.sock
server_id=129
gtid_mode=ON
enforce_gtid_consistency=ON
log-bin=binlog
relay-log=relay-log
relay_log_purge=0
log-slave-updates=true
#rep2
[root@rep2 ~]# cat /etc/my.cnf
[mysqld]
datadir=/data/mysql
socket=/data/mysql/mysql.sock
server_id=130
gtid_mode=ON
enforce_gtid_consistency=ON
log-bin=binlog
relay-log=relay-log
relay_log_purge=0
log-slave-updates=true

4.3配置一主多从复制架构:

#master
mysql> create user 'rep'@'%' identified with mysql_native_password by '123';
Query OK, 0 rows affected (0.00 sec)
mysql> grant replication slave on *.* to 'rep'@'%';
Query OK, 0 rows affected (0.01 sec)
#rep1
mysql> CHANGE REPLICATION SOURCE TO
    -> SOURCE_HOST='192.168.168.128',
    -> SOURCE_USER='rep',
    -> SOURCE_PASSWORD='123',
    -> master_auto_position=1,
    -> SOURCE_SSL=1;
Query OK, 0 rows affected, 3 warnings (0.04 sec)
#rep2
mysql> CHANGE REPLICATION SOURCE TO
    -> SOURCE_HOST='192.168.168.128',
    -> SOURCE_USER='rep',
    -> SOURCE_PASSWORD='123',
    -> master_auto_position=1,
    -> SOURCE_SSL=1;
Query OK, 0 rows affected, 3 warnings (0.01 sec)
mysql> show replica status\G
           Replica_IO_Running: Yes
          Replica_SQL_Running: Yes

5. 配置MHA

5.1 安装MHA包

安装MHA包,下载地址:

https://code.google.com/archive/p/mysql-master-ha/

github下载地址:

https://github.com/yoshinorim/mha4mysql-manager/releases/tag/v0.58

https://github.com/yoshinorim/mha4mysql-node/releases/tag/v0.58

#mha-manager上安装软件包
[root@mha ~]# wget  https://github.com/yoshinorim/mha4mysql-manager/releases/download/v0.58/mha4mysql-manager-0.58-0.el7.centos.noarch.rpm
[root@mha ~]# wget  https://github.com/yoshinorim/mha4mysql-node/releases/download/v0.58/mha4mysql-node-0.58-0.el7.centos.noarch.rpm

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

#解压MHA安装包
[root@mha opt]# unzip MHA-7.zip
Archive:  MHA-7.zip
   creating: MHA-7/
  inflating: MHA-7/mha4mysql-manager-0.58-0.el7.centos.noarch.rpm
  inflating: MHA-7/mha4mysql-manager-0.58.tar.gz
  inflating: MHA-7/mha4mysql-node-0.58-0.el7.centos.noarch.rpm
  inflating: MHA-7/perl-Config-Tiny-2.14-7.el7.noarch.rpm
  inflating: MHA-7/perl-Email-Date-Format-1.002-15.el7.noarch.rpm
  inflating: MHA-7/perl-Log-Dispatch-2.41-1.el7.1.noarch.rpm
  inflating: MHA-7/perl-Mail-Sender-0.8.23-1.el7.noarch.rpm
  inflating: MHA-7/perl-Mail-Sendmail-0.79-21.el7.noarch.rpm
  inflating: MHA-7/perl-MIME-Lite-3.030-1.el7.noarch.rpm
  inflating: MHA-7/perl-MIME-Types-1.38-2.el7.noarch.rpm
  inflating: MHA-7/perl-Net-Telnet-3.03-19.el7.noarch.rpm
  inflating: MHA-7/perl-Parallel-ForkManager-1.18-2.el7.noarch.rpm
[root@mha MHA-7]# ls
mha4mysql-manager-0.58-0.el7.centos.noarch.rpm
perl-Email-Date-Format-1.002-15.el7.noarch.rpm
perl-MIME-Lite-3.030-1.el7.noarch.rpm
mha4mysql-manager-0.58.tar.gz                   
perl-Log-Dispatch-2.41-1.el7.1.noarch.rpm       
perl-MIME-Types-1.38-2.el7.noarch.rpm
mha4mysql-node-0.58-0.el7.centos.noarch.rpm     
perl-Mail-Sender-0.8.23-1.el7.noarch.rpm        
perl-Net-Telnet-3.03-19.el7.noarch.rpm
perl-Config-Tiny-2.14-7.el7.noarch.rpm          
perl-Mail-Sendmail-0.79-21.el7.noarch.rpm       
perl-Parallel-ForkManager-1.18-2.el7.noarch.rpm
#安装这些rpm包
[root@mha MHA-7]# yum localinstall ./*.rpm

所有主机上配置自解析域名

#每台主机都要写
[root@master ~]# cat /etc/hosts
192.168.168.128 master
192.168.168.129 rep1
192.168.168.130 rep2
192.168.168.200 mha

其他三个mysql服务器上安装mha4mysql-node

#在MHA服务器上直接使用scp命令传
[root@mha MHA-7]# for i in {master,rep1,rep2};do scp mha4mysql-node-0.58-0.el7.centos.noarch.rpm root@$i:/root;done
root@master's password:
mha4mysql-node-0.58-0.el7.centos.noarch.rpm           100%   35KB  13.2MB/s   00:00
root@rep1's password:
mha4mysql-node-0.58-0.el7.centos.noarch.rpm           100%   35KB  13.6MB/s   00:00
root@rep2's password:
mha4mysql-node-0.58-0.el7.centos.noarch.rpm           100%   35KB  14.8MB/s   00:00
#分别执行yum安装
[root@master ~]# yum install mha4mysql-node-0.58-0.el7.centos.noarch.rpm -y

5.2 master主机配置

#设置可以远程访问mysql的用户,并设置管理员权限。
#只需要在master上运行即可
mysql> create user 'mhaadm'@'%' identified with mysql_native_password by '123';
mysql> grant all on *.* to 'mhaadm'@'%';

5.3 配置MHA集群的SSH服务

MHA集群中的各节点彼此之间均需要基于ssh互信通信,以实现远程控制及数据管理功能。

#mha主机
[root@mha MHA-7]# ssh-keygen -f /root/.ssh/id_rsa -P "" -q
#给三个数据库主机传递公钥
[root@mha MHA-7]# for i in {master,rep1,rep2};do ssh-copy-id root@$i;done
#给三个数据库主机传递私钥
[root@mha MHA-7]# for i in {master,rep1,rep2};do scp /root/.ssh/id_rsa root@$i:/root/.ssh/;done
id_rsa                                        100% 1679     1.6MB/s   00:00
id_rsa                                        100% 1679     1.7MB/s   00:00
id_rsa                                        100% 1679     2.3MB/s   00:00
#测试
[root@master ~]# for i in {master,rep1,rep2};do ssh root@$i hostname;done
master
rep1
rep2

在这里插入图片描述

5.4 在manager上创建配置文件目录

#/etc/mha创建集群的配置文件,/var/log/mha/app1里创建日志文件
[root@mha ~]# mkdir -p /etc/mha /var/log/mha/app1
[root@mha ~]# vim /etc/mha/app1.cnf
[server default]   #适用于server1,2,3个server的配置
user=mhaadm    #mha管理用户
password=123  #mha管理用户密码
manager_workdir=/var/log/mha/app1  #mha的工作路径
manager_log=/var/log/mha/app1/manager.log  #mha的日志文件
ssh_user=root  #基于ssh的秘钥认证
repl_user=rep  #主从复制的账号
repl_password=123
ping_interval=1  #ping间隔时长
[server1]   #mysql主机信息
hostname=192.168.168.128
ssh_port=22 
candidate_master=1  #设置该主机将来可能成为master候选节点
[server2]
hostname=192.168.168.129
ssh_port=22
candidate_master=1
[server3]
hostname=192.168.168.130
ssh_port=22
no_master=1

5.5 检测各节点间ssh互信通信

[root@mha ~]# masterha_check_ssh --conf=/etc/mha/app1.cnf

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

5.6 检查mysql复制集群的连接配置参数

[root@mha ~]# masterha_check_repl --conf=/etc/mha/app1.cnf

在这里插入图片描述

6. MHA的故障切换

6.1 手动切换

#模拟master宕机
[root@master ~]# /etc/init.d/mysqld stop
Shutting down MySQL......... SUCCESS!
#在mha中做故障切换
[root@mha ~]# masterha_master_switch --master_state=dead --conf=/etc/mha/app1.cnf --dead_master_host=192.168.168.128  --dead_master_port=3306  --new_master_host=192.168.168.129 --new_master_port=3306 --ignore_last_failover

#--ignore_last_failover 表示忽略在/var/log/mha/app1/目录中在切换过程中生成的锁文件
#此时的master变为rep1
mysql> show replicas;
+-----------+------+------+-----------+--------------------------------------+
| Server_Id | Host | Port | Source_Id | Replica_UUID                         |
+-----------+------+------+-----------+--------------------------------------+
|       130 |      | 3306 |       129 | 93b90958-8d6f-11f0-a8c8-000c29fe96af |
+-----------+------+------+-----------+--------------------------------------+
1 row in set (0.00 sec)

6.2 恢复故障mysql节点

[root@master ~]# /etc/init.d/mysqld start
Starting MySQL. SUCCESS!
#将该主机重新加入集群中
mysql> change replication source to
    -> source_host='192.168.168.129',
    -> source_user='rep',
    -> source_password='123',
    -> master_auto_position=1,
    -> source_ssl=1;

在这里插入图片描述

6.3 自动切换

注意:#删除锁文件,如果不删除的话mha无法故障转移成功

[root@mha ~]# rm -rf /var/log/mha/app1/app1.failover.complete

在mha上面输入下面指令让它自己管控

[root@mha ~]# masterha_manager --conf=/etc/mha/app1.cnf

另开一台运行窗口查看mha状态

#输出显示ping_ok说明正常
[root@mha ~]# masterha_check_status --conf=/etc/mha/app1.cnf
app1 (pid:2176) is running(0:PING_OK), master:192.168.168.129

此时的主节点是rep1,模拟rep1宕机

[root@rep1 ~]# /etc/init.d/mysqld stop
Shutting down MySQL........... SUCCESS!
#注意:故障转移完成后,mha-manager将会自动停止运行
#查看转移日志,日志里面的内容就是前面我们手动切换时输出的内容
[root@mha-manager ~]# cat /var/log/mha/app1/manager.log

在rep2上查看主节点是谁

mysql> show replica status\G

在这里插入图片描述

恢复故障的从

[root@rep1 ~]# /etc/init.d/mysqld start
Starting MySQL. SUCCESS!
mysql> CHANGE REPLICATION SOURCE TO
    -> SOURCE_HOST='192.168.168.128',
    -> SOURCE_USER='rep',
    -> SOURCE_PASSWORD='123',
    -> master_auto_position=1,
    -> SOURCE_SSL=1;
Query OK, 0 rows affected, 3 warnings (0.01 sec)
mysql> start replica;

在这里插入图片描述

7. 配置VIP

vip配置可以采用两种方式,一种通过keepalived的方式管理虚拟ip的浮动;另外一种通过脚本方式启动虚拟ip的方式 (即不需要keepalived或者heartbeat类似的软件)。为了防止脑裂发生,推荐生产环境采用脚本的方式来管理虚拟ip,而不是使用keepalived来完成。

7.1 编写脚本

[root@mha ~]# 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
);
#注意此处配置的ip地址和网卡名称
my $vip = '192.168.168.120/24';
my $ssh_start_vip = "/sbin/ip a add $vip dev ens32";
my $ssh_stop_vip = "/sbin/ip a del $vip dev ens32";

GetOptions(
  'command=s' => \$command,
  'ssh_user=s' => \$ssh_user,
  'orig_master_host=s' => \$orig_master_host,
  'orig_master_ip=s' => \$orig_master_ip,
  'orig_master_port=i' => \$orig_master_port,
  'new_master_host=s' => \$new_master_host,
  'new_master_ip=s' => \$new_master_ip,
  'new_master_port=i' => \$new_master_port,
);

exit &main();

sub main {
  print "\n\nIN SCRIPT TEST====$ssh_stop_vip==$ssh_start_vip===\n\n";
  if ( $command eq "stop" || $command eq "stopssh" ) {
    my $exit_code = 1;
    eval {
      print "Disabling the VIP on old master: $orig_master_host \n";
      &stop_vip();
      $exit_code = 0;
    };
    if ($@) {
        warn "Got Error: $@\n";
        exit $exit_code;
    }
    exit $exit_code;
    }
  elsif ( $command eq "start" ) {
    my $exit_code = 10;
    eval {
      print "Enabling the VIP - $vip on the new master - $new_master_host
\n";
      &start_vip();
      $exit_code = 0;
    };
    if ($@) {
      warn $@;
      exit $exit_code;
    }
    exit $exit_code;
  }
  elsif ( $command eq "status" ) {
    print "Checking the Status of the script.. OK \n";
    exit 0;
  }
  else {
    &usage();
    exit 1;
  }
}
sub start_vip() {
  `ssh $ssh_user\@$new_master_host \" $ssh_start_vip \"`;
}
sub stop_vip() {
  return 0 unless ($ssh_user);
  `ssh $ssh_user\@$orig_master_host \" $ssh_stop_vip \"`;
}
sub usage {
  print "Usage: master_ip_failover --command=start|stop|stopssh|status --orig_master_host=host --orig_master_ip=ip --orig_master_port=port --new_master_host=host --new_master_ip=ip --new_master_port=port\n";
}
[root@mha ~]# chmod +x /usr/local/bin/master_ip_failover

7.2 更改mha配置文件

[root@mha ~]# vim /etc/mha/app1.cnf
[server default]
#添加如下信息
master_ip_failover_script=/usr/local/bin/master_ip_failover

7.3 在主库上手动配置第一次的VIP地址

[root@mha ~]# ip a a 192.168.168.120/24 dev ens32

7.4在master节点关闭mysql服务模拟主节点数据崩溃

#在mha上执行下面命令,让其自己监控  加上--ignore_last_failover忽略所文件,否则执行rm -rf /var/log/mha/app1/app1.failover.complete删除所文件,不然无法完成主节点的切换
[root@mha ~]# masterha_manager --conf=/etc/mha/app1.cnf --ignore_last_failover

#模拟主节点宕机
[root@master ~]# /etc/init.d/mysqld stop
Shutting down MySQL........... SUCCESS!

7.5 在rep1上查看ip

此时的rep1成为了新的主节点

#192.168.168.120/24是我设置的VIP
[root@rep1 ~]# ip a show ens32

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值