Mysql(六)基于异步同步的MHA(高可用)架构

目录

一、关于MHA

1、什么是MHA

 2、MHA的组成

3、工作原理:

4、原理

5、MHA的要求

二、MHA的搭建

1、 搭建MHA

2、测试手动failover切换

3、手动实现所有数据库都在线的时候,切换master节点

4、测试半自动failover(手动切换VIP漂移)

5、配置全自动故障转移脚本和vip漂移

测试全自动切换:


一、关于MHA

1、什么是MHA

 MHA(master high   availability)目前是MySQL高可用方面是一个相对成熟的解决方案。

在切换过程中,MHA能做到0-30s内自动完成数据库的切换,并且在切换过程中最大的保持数据的一致性,以达到真正意义上的高可用

说明:

        MHA在监控到master节点故障时,会提升其中拥有最新数据的slave节点成为新的master节点,在此期间,MHA会通过与其

它从节点获取额外信息来避免一致性方面的问题。MHA还提供了master节点的在线切换功能,即按需切换master/slave节点。

        相较于其它HA软件,MHA的目的在于维持MySQL Replication中Master库的高可用性,其最大特点是可以修复多个Slave

之的差异日志,最终使所有Slave保持数据一致,然后从中选择一个充当新的Master,并将其它Slave指向它。

 2、MHA的组成

       MHA Manager(管理节点)和MHA Node(数据节点)这两部分组成。

  •  MHA Manager:通常单独部署在一台独立的机器上或者直接部署在其中一台slave上(不建议后者),管理多个master/slave集群,每个master/slave集群称作一个application;有俩作用:

       (1)Master出现故障的时候,它自动将最新的数据的Slave提升为新的Master,然后将所有的Slave重新指向新的Master

       (2)帮助脚本运行:手动切换master;master/slave状态检测

  • MHA Node:

     运行在每台MySQL服务器上(master/slave/manager),它通过监控具备解析和清理logs功能的脚本来加快故障转移。其作用有:

    (1)复制主节点的binlog数据

    (2)对比从节点的中继日志文件

    (3)无需停止从节点的SQL线程,定时删除中继日志

3、工作原理:

  • 从宕机崩溃的Master保存二进制日志事件(binlog event);
  • 识别含有最新更新的Slave;
  • 应用差异的中继日志(relay log)到其他Slave;
  • 应用从Master保存的二进制日志事件;
  • 提升一个Slave为新的Master;
  • 使其他的Slave连接新的Master进行复制;

4、原理


(1)从宕机崩溃的master保存二进制日志事件(binlog events);

(2)识别含有最新更新的slave;

(3)apply差异的中继日志(relay log)到其他的slave;

(4)apply从master保存的二进制日志事件(binlog events);

(5)提升一个slave为新的master;

(6)使其他的slave连接新的master进行复制。

5、MHA的要求

要求:
(1)需要奇数个节点slave

(2)当一个master节点挂掉之后投票选出一个新的master,偶数个节点会出现票数相同的状况,但奇数个就不会

(3)所有数据节点的数据一致,每一台数据节点都有可能作为master

(4)每个节点都要安装master和slave插件;

当master节点挂了之后,一般选出数据最近的slave节点作为新的master节点。数据最近指的是数据的差异性小。

 

二、MHA的搭建

注意:在做MHA时,只需做好gtid复制就好。

实验环境:

主机IP功能
server1172.25.58.1master
server2172.25.58.2slave  备用mster
server3172.25.58.3slave
server4172.25.58.4MHA  manager

1、 搭建MHA

 数据库信息都在/var/lib/mysql目录下保存,如果更新数据库,可以直接将该目录清空

 systemctl stop mysqld
 cd /var/lib/mysql

server1上:

下载mysql社区办服务器安装包并且安装:下载地址


yum install -y 
mysql-community-client-5.7.24-1.el7.x86_64.rpm 
mysql-community-common-5.7.24-1.el7.x86_64.rpm 
mysql-community-libs-5.7.24-1.el7.x86_64.rpm 
mysql-community-libs-compat-5.7.24-1.el7.x86_64.rpm 
mysql-community-server-5.7.24-1.el7.x86_64.rp

修改配置文件:/etc/my.cnf,添加以下内容

server-id=1
gtid_mode=ON
enforce_gtid_consistency=ON
log_bin=binlog
log_slave_updates=ON

开启mysqld服务,查看随机生成的密码

systemctl start mysqld
cat /var/log/mysqld.log | grep password

 使用该密码进行安全初始化:

mysql_secure_installation

登陆数据库,创建并授权用来做复制的用户,查看master状态

mysql -uroot -pYyz1234..
mysql> CREATE USER 'repl'@'172.25.58.%' IDENTIFIED BY  'Yyz1234..';
mysql> GRANT REPLICATION SLAVE ON *.* TO 'repl'@'172.25.58.%';    
mysql> flush privileges;    #刷新权限
mysql> show master status;   展示msater现在的状态

 

 server2:

同上,一样下载mysql安装包,进行安装,然后配置文件/etc/my.cnf时,添加以下内容:

即,id编号,使用gtid全局复制,打开binlog日志

server-id=2
gtid_mode=ON
enforce_gtid_consistency=ON
log_bin=binlog
log_slave_updates=ON

开启mysqld服务,查看随机生成的密码,然后初始化修改密码

systemctl start mysqld
cat /var/log/mysqld.log | grep password
mysql_secure_installation

 登陆数据库启用gtid

mysql -uroot -pYyz1234..
mysql> CHANGE MASTER TO
    -> MASTER_HOST = '172.25.58.1',
    -> MASTER_USER = 'repl',
    -> MASTER_PASSWORD = 'Yyz1234..',
    -> MASTER_AUTO_POSITION = 1;
mysql> start slave;
mysql> show slave status\G

 

 查看slave的状态时,看到io线程和SQL线程开启则配置完毕~~

gtid配置成功

注意:

此时如果一直是Slave_IO_Running: Connecting,原因可能有

1、网络不通

2、密码不对

3、pos不对

过程中还是得细心~~

server3

下载安装软件包:

yum install -y mysql-community-client.x86_64 
mysql-community-common.x86_64 
mysql-community-libs.x86_64 
mysql-community-libs-compat.x86_64 
mysql-community-server.x86_64

更改配置文件/etc/my.cnf,添加以下内容

server-id=3
gtid_mode=ON
enforce_gtid_consistency=ON
log_bin=binlog
log_slave_updates=ON

开启mysqld服务,查看随机生成的密码,然后初始化密码

systemctl start mysqld
cat /var/log/mysqld.log | grep password
mysql_secure_installation

登陆数据库启用gtid

mysql -uroot -pYyz234..
mysql> CHANGE MASTER TO
    -> MASTER_HOST = '172.25.58.1',
    -> MASTER_USER = 'repl',
    -> MASTER_PASSWORD = 'Yyz1234..',
    -> MASTER_AUTO_POSITION = 1;
mysql> start slave;
mysql> show slave status\G

此时可以看到gtid配置成功

server4:

安装MHA所需安装包及依赖项

生成ssh密钥,管理节点是不需要输入密码,将生成的公钥和私钥传给数据节点(前提做好解析)

ssh-keygen
ssh-copy-id server1
ssh-copy-id server2
ssh-copy-id server3

复制公钥私钥给数据节点,实现互相免密连接

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

在server1、server2和server3上,安装节点数据包:

yum install -y mha4mysql-node-0.58-0.el7.centos.noarch.rpm

server4:

创建一个目录,编辑配置文件

mkdir -p /etc/masterha
cd /etc/masterha/
vim master.cnf

[server default]
manager_workdir=/etc/masterha
manager_log=/var/log/masterha.log   # manager 日志文件
master_binlog_dir=/etc/masterha

password=Yyz1234..             #MySQL管理帐号和密码
user=root 
ping_interval=1
remote_workdir=/tmp
repl_password=Westos+007
repl_user=repl             # 复制帐号和密码
ssh_user=root              # 系统ssh用户

[server1]
hostname=172.25.58.1
port=3306

[server2]
hostname=172.25.58.2
port=3306
candidate_master=1       #设置优先级,master故障时会成为新的master
check_repl_delay=0    #默认如果候选master落后master100M的relay logs,MHA就不选改slave作为新的master

[server3]
hostname=172.25.58.3
port=3306
no_master=1  ##no_master表示这个节点不能作为master

先检查数据节点的ssh连接

masterha_check_ssh --conf=/etc/masterha/master.cnf 

 注意:如果发现报错,说明server1 2 3互相之间不免密,就拷贝server4上的密钥给server1 2 3

再做一次,即使上边已经做过

再检测数据节点的复制功能

masterha_check_repl --conf=/etc/masterha/master.cnf

 有报错:因为server4默认是用root远程连接数据库,但是在配置数据库是已经禁用了root的远程连接

解决:

在server1上授权:

mysql> grant all on *.* to root@'%' identified by 'Yyz1234..';

此时必须将两个slave(server1和server2)节点设置只读(不写在配置文件里,因为slave随时可能切换为master)

server2和server3都进行设置:

set global read_only=1;

此时在server4上再进行复制功能检测:

masterha_check_repl --conf=/etc/masterha/master.cnf

此时成功~~~

 

说道MHA功能的时候,master可以进行自动监测,也可以手动切换master,那么就先进行手动切换:

2、测试手动failover切换

server4:

先关闭manager,不关的话切不了,manager就是自动切换的工具

masterha_stop --conf=/etc/masterha/master.cnf

server1:

systemctl stop mysqld

server4:进行切换,将主切换到server2上

masterha_master_switch --master_state=dead --conf=/etc/masterha/master.cnf --dead_master_host=172.25.58.1 --dead_master_ip=172.25.58.1 --dead_master_port=3306 --new_master_host=172.25.58.2 --new_master_port=3306

注意:

手动切换之前,需要保证主从同步正常,repl复制用户能够远程连接

在server3上进行测试

看其master是否更改:

show slave status\G;

server1:

手动开启server1,作为slave加入集群

开启数据库,登录数据库添加slave信息:

systemctl start mysqld


mysql -uroot -pYyz1234..
mysql> CHANGE MASTER TO MASTER_HOST = '172.25.58.2', MASTER_USER = 'repl', MASTER_PASSWORD = 'Yyz1234..', MASTER_AUTO_POSITION = 1;
mysql> start slave;
mysql> show slave status\G

å¨è¿éæå¥å¾çæè¿°

【注意】:现在就完成了一次手动切换,这时会在MHA节点/etc/masterha目录下生成一个master.failover.complete文件,是来记录failover情况的,再进行failover时必须先把这个文件删除,不然不会failover.

3、手动实现所有数据库都在线的时候,切换master节点

server4

删除故障文件

[root@server4 ~]# cd /etc/masterha/
[root@server4 masterha]# ls
[root@server4 masterha]# rm -fr   master.failover.complete

server4:将master又重新切换到server1上:

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

在server3上测试:

mysql> show slave status\G;看是否切换成功

4、测试半自动failover(手动切换VIP漂移)

server4:

先清理master.failover.complete,再开启MHA  manager管理节点

rm -fr /etc/masterha/master.failover.complete 

nohup masterha_manager --conf=/etc/masterha/master.cnf &>/dev/null &

mha manager自带守护进程,会定时探测集群中的master节点,当master出现故障时,它可以自动将最新数据的slave提升为新的master,然后将所有其他的slave重新指向新的master。整个故障转移过程对应用程序完全透明。

server1:

å¨è¿éæå¥å¾çæè¿°

发现进程关不掉,此时手动关闭mysqld进程才会关闭

 systemctl stop mysqld
 ps ax | grep mysql  #查看进程退出

server4:日志最后可以发现,server2已经成了新的master了。

cat /var/log/masterha.log

因为此时manager进程退出,所以需要脚本:

server1:将server1再加回集群:

systemctl start mysqld
mysql -uroot -pYyz1234..
mysql>  CHANGE MASTER TO MASTER_HOST = '172.25.58.2', MASTER_USER = 'repl', MASTER_PASSWORD = 'Yyz1234..', MASTER_AUTO_POSITION = 1;
mysql> start slave;
mysql> show slave status\G

å¨è¿éæå¥å¾çæè¿°

可以看到现在的master的确就是server2

5、配置全自动故障转移脚本和vip漂移

server4:

编辑master.cnf,在[server default] 下加入脚本启动路径:

master_ip_failover_script= /usr/local/bin/master_ip_failover
master_ip_online_change_script= /usr/local/bin/master_ip_online_change

 

官网上下载脚本,编辑master_ip_failover 和 master_ip_online_change 两个故障切换脚本

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.58.100/24';
my $key = '1';
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";
}

master_ip_online_change脚本内容如下:

#!/usr/bin/env perl
use strict;  
use warnings FATAL =>'all';  
  
use Getopt::Long;  
  
my $vip = '172.25.58.100/24';  # Virtual IP  
my $key = "1";  
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";  
}

配置自动添加和删除vip

cp master_ip_failover master_ip_online_change /usr/local/bin
cd /usr/local/
cd bin/
chmod +x master_ip_failover master_ip_online_change   给予执行权限

此时master是server2,先给server2添加VIP:

server2:

ip addr add 172.25.58.100/24 dev eth0

此时VIP漂移:

在server4上:

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

server1上进行查看,vip漂移过来,也成为新的master

 

 

测试全自动切换:

删除server4上 /etc/masterha下的master.failover.complete

开启manager(MHA管理)

nohup masterha_manager --conf=/etc/masterha/app1.cnf &>/dev/null &

server1:

模拟故障,关闭mysqld

server4:

cat /var/log/masterha.log

 可以看到vip在进行漂移

 可以看到切换成功,vip也成功漂移~~~

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值