MySQL高可用架构之MHA的手动部署

MHA介绍

MHA(Master High Availability)目前在MySQL高可用方面是一个相对成熟的解决方案,它由日本DeNA公司youshimaton(现就职于Facebook公司)开发,是一套优秀的作为MySQL高可用性环境下故障切换和主从提升的高可用软件。在MySQL故障切换过程中,MHA能做到在0~30秒之内自动完成数据库的故障切换操作,并且在进行故障切换的过程中,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没法保存二进制日志,只进行故障转移而丢失了最新的数据。使用MySQL 5.5的半同步复制,可以大大降低数据丢失的风险。MHA可以与半同步复制结合起来。如果只有一个slave已经收到了最新的二进制日志,MHA可以将最新的二进制日志应用于其他所有的slave服务器上,因此可以保证所有节点的数据一致性。

目前MHA主要支持一主多从的架构,要搭建MHA,要求一个复制集群中必须最少有三台数据库服务器,一主二从,即一台充当master,一台充当备用master,另外一台充当从库,因为至少需要三台服务器,出于机器成本的考虑,淘宝也在该基础上进行了改造,目前淘宝TMHA已经支持一主一从。

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

图解:
MySQL高可用架构之MHA的手动部署_第1张图片

环境:
Server1:172.25.254.1 master
Server2:172.25.254.2 slave
Server3:172.25.254.3 slave
Server4:172.25.254.4 manager
mysql版本: mysql5.7
关于本篇博客中涉及的所有软件包下载可参考此博客:https://blog.csdn.net/qq657886445/article/details/83662696

先简单配置主从复制,一主两从
此处采用基于gtid的主从复制,其详细配置可参考博客:https://blog.csdn.net/qq657886445/article/details/83588877

由于搭建MHA任何一台虚拟机都有可能成为master所以每台虚拟机mysql配置文件中都需添加开启二进制日志的参数
MySQL高可用架构之MHA的手动部署_第2张图片
MySQL高可用架构之MHA的手动部署_第3张图片
MySQL高可用架构之MHA的手动部署_第4张图片
一主二从结果如下图
MySQL高可用架构之MHA的手动部署_第5张图片
MySQL高可用架构之MHA的手动部署_第6张图片
server1,server2,server3都安装mha4mysql-node

yum install -y mha4mysql-node-0.56-0.el6.noarch.rpm

MySQL高可用架构之MHA的手动部署_第7张图片

MySQL高可用架构之MHA的手动部署_第8张图片

MySQL高可用架构之MHA的手动部署_第9张图片

Server4

yum install -y mha4mysql-manager-0.56-0.el6.noarch.rpm perl-* mha4mysql-node-0.56-0.el6.noarch.rpm

MySQL高可用架构之MHA的手动部署_第10张图片

mkdir /etc/masterha
cd /etc/masterha/
vim app1.cnf                           #编写配置文件
[server default]
manager_workdir=/etc/masterha             #manager的工作目录
manager_log=/etc/masterha/manager.log     #manager的日志地址
master_binlog_dir=/var/lib/mysql          #master 保存binlog的位置,以便MHA可以找到master的日志
#master_ip_failover_script=/usr/local/bin/master_ip_failover
#master_ip_online_change_script= /usr/local/bin/master_ip_online_change 
password=Westos.3q                        #mysql中root用户的密码
user=root                                 #监控用户root
ping_interval=1                           #设置监控主库,发送ping包的时间间隔
remote_workdir=/tmp                       #设置远端mysql在发生切换时binlog的保存位置
repl_password=Westos.3q                   #设置复制用户的密码
repl_user=repl                            #设置复制用户名                
secondary_check_script=/usr/bin/masterha_secondary_check -s server3 -s server1
ssh_user=root                             #设置ssh的登录用户名

[server1]
hostname=172.25.254.1
port=3306

[server2]
hostname=172.25.254.2
port=3306
    candidate_master=1          #优先选为新的master,即使这个主库不是集群中事件最新的slave
    check_repl_delay=0          #选择新的master时MHA会忽略复制延迟

[server3]
hostname=172.25.254.3
port=3306

MySQL高可用架构之MHA的手动部署_第11张图片

四个节点需要ssh的免密认证
生成认证key

ssh-kengen  #全部回车即可

MySQL高可用架构之MHA的手动部署_第12张图片

加密服务

cd ~/.ssh/
ssh-copy-id 172.25.254.4

MySQL高可用架构之MHA的手动部署_第13张图片

分发密钥

scp -r .ssh/ server1:
scp -r .ssh/ server2:
scp -r .ssh/ server3:

MySQL高可用架构之MHA的手动部署_第14张图片

测试:
因为每个节点第一次连接时都会确认是否连接,所以各节点都挨着互相连一遍

ssh 172.25.24.4 
ssh 172.25.24.3
ssh 172.25.24.2
ssh 172.25.24.1

MySQL高可用架构之MHA的手动部署_第15张图片

MySQL高可用架构之MHA的手动部署_第16张图片

MySQL高可用架构之MHA的手动部署_第17张图片

MySQL高可用架构之MHA的手动部署_第18张图片

使用免密检测脚本检测:

masterha_check_ssh --conf=/etc/masterha/app1.cnf      #全部成功则此步成功

MySQL高可用架构之MHA的手动部署_第19张图片

登陆master端数据库授权

grant all on *.* to root@'%' identified by 'Westos.3q';
grant replication slave on *.* to repl@'%' identified by 'Westos.3q';

MySQL高可用架构之MHA的手动部署_第20张图片

在server4执行用户检测脚本,需使复制用户存在和允许管理员用户的远程登陆

masterha_check_repl --conf=/etc/masterha/app1.cnf          #最后显示OK即为成功

MySQL高可用架构之MHA的手动部署_第21张图片

启动服务

nohup masterha_manager --conf=/etc/masterha/app1.cnf  --ignore_last_failover &     #启动服务并打入后台
masterha_check_status --conf=/etc/masterha/app1.cnf     #查看状态

MySQL高可用架构之MHA的手动部署_第22张图片

测试:
1.手动切换
1)将正在运行的master转换为指定的master。指定新master为server2

masterha_master_switch --conf=/etc/masterha/app1.cnf --master_state=alive --new_master_host=172.25.254.2 --new_master_port=3306 --orig_master_is_new_slave --running_updates_limit=10000

我做的时候在第一次输入yes后出现如下报错,需关闭MHA
MySQL高可用架构之MHA的手动部署_第23张图片
此时关闭MHA再次测试,一直输入yes即可
MySQL高可用架构之MHA的手动部署_第24张图片
MySQL高可用架构之MHA的手动部署_第25张图片
查看各节点slave状态,可以发现server2已成为新的master,server1和server3为slave
MySQL高可用架构之MHA的手动部署_第26张图片MySQL高可用架构之MHA的手动部署_第27张图片
MySQL高可用架构之MHA的手动部署_第28张图片

2)手动切换故障机器
关闭server2上的mysql
MySQL高可用架构之MHA的手动部署_第29张图片
指定新master为server3,执行命令一直输入yes

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

MySQL高可用架构之MHA的手动部署_第30张图片
分别在server3和server1上查看slave状态,master切换成功
MySQL高可用架构之MHA的手动部署_第31张图片
MySQL高可用架构之MHA的手动部署_第32张图片
当再次启动server2的mysql时,需要先关闭slave重新指定master后再开启slave

change master to master_host='172.25.254.3',master_user='repl',master_password='Westos.3q',master_auto_position=1;

MySQL高可用架构之MHA的手动部署_第33张图片

2.自动切换
手动关闭master端mysql,自动切换需开启mha服务。
在这里插入图片描述
MySQL高可用架构之MHA的手动部署_第34张图片

在server4查看日志

cat /etc/masterha/manager.log       #master已切换到server2

MySQL高可用架构之MHA的手动部署_第35张图片

在server2和server1查看,已自动切换
MySQL高可用架构之MHA的手动部署_第36张图片
MySQL高可用架构之MHA的手动部署_第37张图片

MHA在线切换脚本结合vip

修改/etc/masterha/app1.cnf文件
vim /etc/masterha/app1.cnf #取消注释
MySQL高可用架构之MHA的手动部署_第38张图片

cat /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 = '172.25.254.100/24';
my $ssh_start_vip = "/sbin/ip addr add $vip dev eth0";
my $ssh_stop_vip = "/sbin/ip addr del $vip dev eth0";

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";
}

cat /usr/local/bin/master_ip_online_change

#!/usr/bin/env perl
use strict;  
use warnings FATAL =>'all';  
  
use Getopt::Long;  
  
my $vip = '172.25.254.100/24';  # Virtual IP  
my $ssh_start_vip = "/sbin/ip addr add $vip dev eth0";  
my $ssh_stop_vip = "/sbin/ip addr del $vip dev eth0";  
my $exit_code = 0;  
  
my (  
  $command,              $orig_master_is_new_slave, $orig_master_host,  
  $orig_master_ip,       $orig_master_port,         $orig_master_user,  
  $orig_master_password, $orig_master_ssh_user,     $new_master_host,  
  $new_master_ip,        $new_master_port,          $new_master_user,  
  $new_master_password,  $new_master_ssh_user,  
);  
GetOptions(  
  'command=s'                => \$command,  
  'orig_master_is_new_slave' => \$orig_master_is_new_slave,  
  'orig_master_host=s'       => \$orig_master_host,  
  'orig_master_ip=s'         => \$orig_master_ip,  
  'orig_master_port=i'       => \$orig_master_port,  
  'orig_master_user=s'       => \$orig_master_user,  
  'orig_master_password=s'   => \$orig_master_password,  
  'orig_master_ssh_user=s'   => \$orig_master_ssh_user,  
  'new_master_host=s'        => \$new_master_host,  
  'new_master_ip=s'          => \$new_master_ip,  
  'new_master_port=i'        => \$new_master_port,  
  'new_master_user=s'        => \$new_master_user,  
  'new_master_password=s'    => \$new_master_password,  
  'new_master_ssh_user=s'    => \$new_master_ssh_user,  
);  
  
  
exit &main();  
  
sub main {  
  
#print "\n\nIN SCRIPT TEST====$ssh_stop_vip==$ssh_start_vip===\n\n";  
  
if ( $command eq "stop" || $command eq "stopssh" ) {  
  
        # $orig_master_host, $orig_master_ip, $orig_master_port are passed.  
        # If you manage master ip address at global catalog database,  
        # invalidate orig_master_ip here.  
        my $exit_code = 1;  
        eval {  
            print "\n\n\n***************************************************************\n";  
            print "Disabling the VIP - $vip on old master: $orig_master_host\n";  
            print "***************************************************************\n\n\n\n";  
&stop_vip();  
            $exit_code = 0;  
        };  
        if ($@) {  
            warn "Got Error: $@\n";  
            exit $exit_code;  
        }  
        exit $exit_code;  
}  
elsif ( $command eq "start" ) {  
  
        # all arguments are passed.  
        # If you manage master ip address at global catalog database,  
        # activate new_master_ip here.  
        # You can also grant write access (create user, set read_only=0, etc) here.  
my $exit_code = 10;  
        eval {  
            print "\n\n\n***************************************************************\n";  
            print "Enabling the VIP - $vip on new master: $new_master_host \n";  
            print "***************************************************************\n\n\n\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";  
        `ssh $orig_master_ssh_user\@$orig_master_host \" $ssh_start_vip \"`;  
        exit 0;  
}  
else {  
&usage();  
        exit 1;  
}  
}  
  
# A simple system call that enable the VIP on the new master  
sub start_vip() {  
`ssh $new_master_ssh_user\@$new_master_host \" $ssh_start_vip \"`;  
}  
# A simple system call that disable the VIP on the old_master  
sub stop_vip() {  
`ssh $orig_master_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";  
}

将脚本放入指定目录中
MySQL高可用架构之MHA的手动部署_第39张图片

测试:
因为master端现在没有vip,所有先在master端添加vip,若不添加vip会报错,server4查看可见此时master为server2
在这里插入图片描述
MySQL高可用架构之MHA的手动部署_第40张图片

手动切换时需关闭MHA
masterha_check_status --conf=/etc/masterha/app1.cnf
在这里插入图片描述

手动将master切换为server3,先在server3查看是否有vip
MySQL高可用架构之MHA的手动部署_第41张图片

在server4上进行切换

masterha_master_switch --conf=/etc/masterha/app1.cnf --master_state=alive --new_master_host=172.25.254.3 --new_master_port=3306 --orig_master_is_new_slave --running_updates_limit=10000

MySQL高可用架构之MHA的手动部署_第42张图片

查看server2与server3ip,可以看见server2上vip飘逸到server3上了
MySQL高可用架构之MHA的手动部署_第43张图片
MySQL高可用架构之MHA的手动部署_第44张图片

查看mysql各节点slave状态
MySQL高可用架构之MHA的手动部署_第45张图片
MySQL高可用架构之MHA的手动部署_第46张图片
MySQL高可用架构之MHA的手动部署_第47张图片

你可能感兴趣的:(MySQL高可用架构之MHA的手动部署)