企业—Mysql的高可用架构搭建(同时实现读写分离)及VIP

一.Mysql高可用架构简介

1.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。整个故障转移过程对应用程序完全透明。

2.MHA的优点

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

3.MHA的处理流程

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

4.MHA的manager和node相关参数的介绍

  • 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信息

  • Node工具包(这些工具通常由MHA Manager的脚本触发,无需人为操作)主要包括以下几个工具:

  • save_binary_logs 保存和复制master的二进制日志

  • apply_diff_relay_logs 识别差异的中继日志事件并将其差异的事件应用于其他的slave

  • filter_mysqlbinlog 去除不必要的ROLLBACK事件(MHA已不再使用这个工具)

  • purge_relay_logs 清除中继日志(不会阻塞SQL线程)

二.MHA之mysql的高可用集群架构的搭建

1.实验环境

主机名(IP) 服务
server1(172.25.254.1) master
server2(172.25.254.2) slave(备master)
server3(172.25.254.3) slave
server4(172.25.254.4) MHA

2.在server1,server2和server3上配置基于gtid的主从复制

  • a.重新刷新数据库
    server1,server2,server3操作相同。
    在这里插入图片描述
    企业—Mysql的高可用架构搭建(同时实现读写分离)及VIP_第1张图片
    在这里插入图片描述
    b.编辑server1,server2,server3的数据库配置文件
    在这里插入图片描述
    server1:
    在这里插入图片描述
    server2:
    在这里插入图片描述
    server3:
    企业—Mysql的高可用架构搭建(同时实现读写分离)及VIP_第2张图片
    c.开启server1,2,3的数据库
    在这里插入图片描述
    d.查看数据库密码登录数据库并且修改密码(server1,2,3相同)
grep password /var/log/mysqld.log

在这里插入图片描述
e.主从配置
server1(主):
注:因为进行MHA搭建每一个主机都有可能是主也有可能是从,所以都要安装主从设备的插件.

mysql> grant replication slave on *.* to repl@'172.25.254.%' identified by 'Zhulili+123';
mysql> install plugin rpl_semi_sync_master soname 'semisync_master.so;
mysql> install plugin rpl_semi_sync_slave soname 'semisync_slave.so';
mysql> set global rpl_semi_sync_master_enabled=1;
mysql> set global rpl_semi_sync_master_timeout=10000000000000;

企业—Mysql的高可用架构搭建(同时实现读写分离)及VIP_第3张图片
企业—Mysql的高可用架构搭建(同时实现读写分离)及VIP_第4张图片
server2(从):

mysql> change master to master_host='172.25.254.1', master_user='repl',master_password='Zhulili+123',master_auto_position=1;
mysql> install plugin rpl_semi_sync_master soname 'semisync_master.so';
mysql> install plugin rpl_semi_sync_slave soname 'semisync_slave.so';
mysql> set global rpl_semi_sync_slave_enabled=1;
mysql> stop slave io_thread;
mysql> start slave io_thread;
mysql> start slave;

企业—Mysql的高可用架构搭建(同时实现读写分离)及VIP_第5张图片
server3(从):

mysql> change master to master_host='172.25.254.1', master_user='repl',master_password='Zhulili+123',master_auto_position=1;
mysql> install plugin rpl_semi_sync_master soname 'semisync_master.so';
mysql> install plugin rpl_semi_sync_slave soname 'semisync_slave.so';
mysql> set global rpl_semi_sync_slave_enabled=1;
mysql> stop slave io_thread;
mysql> start slave io_thread;
mysql> start slave;

企业—Mysql的高可用架构搭建(同时实现读写分离)及VIP_第6张图片
f.测试:
server1:(写入数据)

mysql> create database westos;
mysql> use westos;
Database changed
mysql> create table userlist(
    -> username varchar(10) not null,
    -> password varchar(15) not null);
mysql> insert into userlist values ('user1','123')
mysql> insert into userlist values ('user2','123')
mysql> insert into userlist values ('user3','123')

企业—Mysql的高可用架构搭建(同时实现读写分离)及VIP_第7张图片
在server2上查看:
企业—Mysql的高可用架构搭建(同时实现读写分离)及VIP_第8张图片
在server3上查看:
企业—Mysql的高可用架构搭建(同时实现读写分离)及VIP_第9张图片
则发现数据已经同步成功

3.在server4上的MHA的配置

a.官网下载需要用到的安装包
企业—Mysql的高可用架构搭建(同时实现读写分离)及VIP_第10张图片
b.安装
企业—Mysql的高可用架构搭建(同时实现读写分离)及VIP_第11张图片
c.因为MHA中的master于slave之间是通过ssh服务来进行保存二进制日志的所以要保证server4,server3,server2,server1之间相互不用密码登录就可以直接连接

  • 在server4上生成钥匙和锁,并将钥匙发给server1,2,3
    企业—Mysql的高可用架构搭建(同时实现读写分离)及VIP_第12张图片
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
  • 上述之是解决了server4能直接连接server1,2,3但是serevr1,2,3之间是无法直接连接的,所以需要将公钥和私钥都发给server1,2,和3.
    企业—Mysql的高可用架构搭建(同时实现读写分离)及VIP_第13张图片

则server1,2,3,4之间都可以直接相互连接

d.将server4上数据节点node的安装包分别发给server1,2,3
企业—Mysql的高可用架构搭建(同时实现读写分离)及VIP_第14张图片
e.在server1,2,3上分别安装节点node的包

[root@server1 ~]# yum install mha4mysql-node-0.58-0.el7.centos.noarch.rpm -y
[root@server2 ~]# yum install mha4mysql-node-0.58-0.el7.centos.noarch.rpm -y
[root@server3 ~]# yum install mha4mysql-node-0.58-0.el7.centos.noarch.rpm -y

f.在server4上编写高可用的配置文件

  • 创建高可用配置文件的目录
[root@server4 ~]# mkdir -p  /etc/masterha
  • 编辑mha的配置文件
[root@server4 ~]# vim /etc/masterha/app1.cnf
文件编辑内容及解释如下:
[server default]
manager_workdir=/etc/masterha //设置manager的工作目录
manager_log=/var/log/masterha.log  //设置manager的日志
master_binlog_dir=/etc/masterha 设置master 保存binlog的位置,以便MHA可以找到master的日志
password=Zhulili+123  //设置mysql中root用户的密码,这个密码是前文中创建监控用户的那个密
user=root  //设置监控用户root
ping_interval=1  //设置监控主库,发送ping包的时间间隔,默认是3秒,尝试三次没有回应的时候自动进行failover
remote_workdir=/tmp  //设置远端mysql在发生切换时binlog的保存位置
repl_password=Zhulili+123  //设置复制用户的密码
repl_user=repl  //设置复制环境中的复制用户名
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   //默认情况下如果一个slave落后master 100M的relay logs的话,MHA将不会选择该slave作为一个新的master,因为对于这个slave的恢复需要花费很长时间,通过设置check_repl_delay=0,MHA触发切换在选择一个新的master的时候将会忽略复制延时,这个参数对于设置了candidate_master=1的主机非常有用,因为这个候选主在切换的过程中一定是新的master

[server3]
hostname=172.25.254.3
port=3306
no_master=1   //设置server3不能成为master                                                                      

h.在server4上查看ssh的配置是否成功
企业—Mysql的高可用架构搭建(同时实现读写分离)及VIP_第15张图片
显示ssh配置成功
i.查看mysql的复制情况
企业—Mysql的高可用架构搭建(同时实现读写分离)及VIP_第16张图片出现了错误,是因为在server2和server3这俩个slave的从端没有添加只读

解决如下:

  • server2:设置只读
    企业—Mysql的高可用架构搭建(同时实现读写分离)及VIP_第17张图片
  • server3上也设置只读

企业—Mysql的高可用架构搭建(同时实现读写分离)及VIP_第18张图片

  • 在server4上再次检测复制用户发现还是失败是因为没有对master的mysql的root用户授予远程登录的权限,用此在server1上添加root用户权限
    企业—Mysql的高可用架构搭建(同时实现读写分离)及VIP_第19张图片
  • 在server4上再次检测复制用户
    在这里插入图片描述
    标示中没有error则显示检测成功

4.MHA的测试

  • 手动同步

a.关闭server1即master然后在server4上将手动将master转到server2上
注:在server4上进行手动切换前必须先关掉server1上的mysql否则,手动切换不成功
在这里插入图片描述

[root@server4 ~]# masterha_master_switch --master_state=dead --conf=/etc/masterha/app1.cnf --dead_master_ip=172.25.254.1 --dead_master_host=172.25.254.1 --dead_master_port=3306 --new_master_host=172.25.254.2 --new_master_port=3306

企业—Mysql的高可用架构搭建(同时实现读写分离)及VIP_第20张图片
显示切换成功

//在server2上查看因为server2已成为主,所以不显示slave状态:
在这里插入图片描述
//在server3上查看,主已经切换为server2(辅slave)
企业—Mysql的高可用架构搭建(同时实现读写分离)及VIP_第21张图片
c.打开server1的mysqld,因为server1的服务再次开启默认已经为salve了,所以需要给其授予slave;
在这里插入图片描述
企业—Mysql的高可用架构搭建(同时实现读写分离)及VIP_第22张图片
查看其slave状态显示为server2
企业—Mysql的高可用架构搭建(同时实现读写分离)及VIP_第23张图片

  • 测试:俩个主备都为master都开启

a.首先删除/etc/masterha/app1.failover.complete,否则再次转换不能成功

[root@server4 ~]# cd /etc/masterha/
[root@server4 masterha]# ls
app1.cnf  app1.failover.complete
[root@server4 masterha]# rm -rf app1.failover.complete 

b.在server4上手动切换新的master为server1

[root@server4 masterha]# masterha_master_switch  --conf=/etc/masterha/app1.cnf --master_state=alive --new_master_host=172.25.254.1 --new_master_port=3306 --orig_master_is_new_slave --running_updates_limit=10000   

//server1上再次查看
企业—Mysql的高可用架构搭建(同时实现读写分离)及VIP_第24张图片
//server2(以前的主)再次查看
企业—Mysql的高可用架构搭建(同时实现读写分离)及VIP_第25张图片
发现server2主动转为slave,不用进行授权及开启slave操作

  • 测试:自动切换

a.server4上开启mha
启动参数介绍

  • –remove_dead_master_conf 该参数代表当发生主从切换后,老的主库的ip将会从配置文件中移除。
  • –ignore_last_failover 在缺省情况下,如果MHA检测到连续发生宕机,且两次宕机间隔不足8小时的话,则不会进行Failover,之所以这样限制是为了避免ping-pong效应。该参数代表忽略上次MHA触发切换产生的文件,默认情况下,MHA发生切换后会在日志目录,也就是上面我设置的/data产生app1.failover.complete文件,下次再次切换的时候如果发现该目录下存在该文件将不允许触发切换,除非在第一次切换后收到删除该文件,为了方便,这里设置为–ignore_last_failover。

在这里插入图片描述
在这里插入图片描述
b.手动关掉master(server1)
在这里插入图片描述
//在server2上看不到slave,server2(辅master)已为master
企业—Mysql的高可用架构搭建(同时实现读写分离)及VIP_第26张图片
//server3上查看:
企业—Mysql的高可用架构搭建(同时实现读写分离)及VIP_第27张图片
c.打开server1的mysqld需要手动添加slave并且打开slave
在这里插入图片描述
在这里插入图片描述
查看slave状态,发现其master为server2
企业—Mysql的高可用架构搭建(同时实现读写分离)及VIP_第28张图片

二.VIP配置

1.编辑配置文件
在这里插入图片描述
配置文件添加内容如下:
企业—Mysql的高可用架构搭建(同时实现读写分离)及VIP_第29张图片
2.在/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.0.100/24';
my $key = '1';
my $ssh_start_vip = "/sbin/ifconfig eth0:$key $vip";
my $ssh_stop_vip = "/sbin/ifconfig eth0:$key down";

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.0.100/24';  # Virtual IP  
my $key = "1";  
my $ssh_start_vip = "/sbin/ifconfig eth0:$key $vip";  
my $ssh_stop_vip = "/sbin/ifconfig eth0:$key down";  
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  

关于这俩个vip的脚本文件也可以通过以下方式获取:

  • 官网下载mha高可用的manager的安装包并且解压
    在这里插入图片描述
  • 在相应目录下就会有这俩个脚本
    企业—Mysql的高可用架构搭建(同时实现读写分离)及VIP_第30张图片
    c.编辑这俩个脚本文件,需要修改的内容如下:
    在这里插入图片描述
    文件修改内容如下:
    在这里插入图片描述
    在这里插入图片描述
    文件修改内容如下:
    在这里插入图片描述
    d.给俩个脚本添加执行权限
    企业—Mysql的高可用架构搭建(同时实现读写分离)及VIP_第31张图片
    e.给master(server2)上添加vip
    企业—Mysql的高可用架构搭建(同时实现读写分离)及VIP_第32张图片
  • 测试:

手动转换:
a.转化master到server1

[root@server4 bin]# masterha_master_switch  --conf=/etc/masterha/app1.cnf --master_state=alive --new_master_host=172.25.254.1 --new_master_port=3306 --orig_master_is_new_slave --running_updates_limit=10000

在这里插入图片描述
b.查看vip漂到server1上
企业—Mysql的高可用架构搭建(同时实现读写分离)及VIP_第33张图片
自动转换
a.开启mha的自动转换
在这里插入图片描述
b.关掉server1(master)
在这里插入图片描述
c.查看vip漂到server2(新master上)
企业—Mysql的高可用架构搭建(同时实现读写分离)及VIP_第34张图片
真机远程登录查看

mysql -h 172.25.19.100 -u root -p

你可能感兴趣的:(企业—Mysql的高可用架构搭建(同时实现读写分离)及VIP)