MySQL高可用方案之MHA

一、MySQL高可用方案

什么是高可用?高可用其实就是可以实现自动故障转移。当主节点挂了之后其他节点可以自动顶上,防止节点出现故障时MySQL不能对外提供服务。

MySQL的高可用解决方案其实有很多种(想了解自行百度),这里只说其中一种:MHA。这也是当前比较主流的方案。

二、MHA详解

  • 什么是MHA?

    MHA 是 Master High Availability 的缩写,直译过来就是“主机高可用”。它是一款当前主流的相对成熟的MySQL高可用方案之一,能做到在0~30s内自动完成MySQL的故障切换操作,在master服务器不宕机的情况下,基本能保证数据的一致性。

  • MHA的组成

    MHA由两部分组成,MHA Manager 和 MHA Node

    1. MHA Manager(管理节点)

      MHA Manager可以单独部署在一台独立的机器上管理多个master-slave集群,也可以部署在master-slave集群中任意一台机器上,建议单独部署在一台独立的机器上

    2. MHA Node(数据节点)

      MHA Node运行在每台MySQL服务器上,是MHA Manager的员工,接收Manager的命令并执行

  • MHA的工作原理

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

    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工具包:

    组件名称 组件说明
    save_binary_logs 保存和复制master的二进制日志
    apply_diff_relay_logs 识别差异的中继日志事件并将其差异的事件应用于其他的slave
    filter_mysqlbinlog 去除不必要的ROLLBACK事件(MHA已不再使用这个工具)
    purge_relay_logs 清除中继日志(不会阻塞SQL线程)
  • manager和node的工具包可以通过我的网盘下载安装包

    链接:https://pan.baidu.com/s/1WQHUrFVBpafLveNfXxaPUg 
    提取码:3w31 
    

三、搭建MHA

在搭建MHA之前应该先保证已经安装配置好了MySQL的主从/集群。因为既然是高可用架构,那么针对的肯定是多台设备,单机的话谈不上高可用。

MySQL的主从搭建过程这里就不说了,可以看这里:MySQL搭建主从架构

本次搭建环境:centos7.8 + mysql5.7.31

角色 IP地址 以下简称 server_id
MHA Manager 192.168.241.104 104 -
mysql master 192.168.241.101 101 101
mysql slave1 192.168.241.102 102 102
mysql slave2 192.168.241.103 103 103
  1. 秘钥互信

    因为MHA在故障转移时要移动binlog日志和中继日志,需要在节点进行ssh通信,所以要设置下秘钥互信,也就是需要配置下免密登录。

    在所有的机器上执行以下命令

    cd ~
    ssh-keygen -t rsa #一路回车
    cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
    chmod 600 ~/.ssh/authorized_keys
    

    在104机器上执行以下命令

    ssh 192.168.241.101 cat ~/.ssh/id_rsa.pub >>~/.ssh/authorized_keys
    ssh 192.168.241.102 cat ~/.ssh/id_rsa.pub >>~/.ssh/authorized_keys
    ssh 192.168.241.103 cat ~/.ssh/id_rsa.pub >>~/.ssh/authorized_keys
    scp ~/.ssh/authorized_keys 192.168.241.101:~/.ssh/
    scp ~/.ssh/authorized_keys 192.168.241.102:~/.ssh/
    scp ~/.ssh/authorized_keys 192.168.241.103:~/.ssh/
    

    执行完成后需要在每台机器上测试一遍,看是否配置成功。执行 ssh root@192.168.241.101(其他机器的IP) ,如果可以直接登录,输入 ip a 发现IP确实变成了登录的那台,证明互信建立成功。

    [root@bogon ~]# ip a | grep 104
        inet 192.168.241.104/24 brd 192.168.241.255 scope global noprefixroute ens32
    [root@bogon ~]#
    [root@bogon ~]# ssh root@192.168.241.101
    Last login: Sun Jun 27 22:10:37 2021 from 192.168.241.101
    [root@bogon ~]# ip a | grep 101
        inet 192.168.241.101/24 brd 192.168.241.255 scope global noprefixroute ens32
    [root@bogon ~]#
    
  2. 在所有机器上安装依赖

    yum install -y perl-ExtUtils-CBuilder perl-ExtUtils-MakeMaker perl-CPAN perl-DBD-MySQL perl-Config-Tiny perl-Log-Dispatch perl-Parallel-ForkManager perl-Time-HiRes
    
  3. 安装 MHA Node组件

    在所有机器上安装node工具包

    cd /usr/local/src/
    mkdir mha && cd mha
    # 将mha4mysql-node-0.58.tar.gz压缩包上传到这
    tar -zxvf mha4mysql-node-0.58.tar.gz
    cd mha4mysql-node-0.58
    # 校验
    perl Makefile.PL 
    make && make install
    

    安装完成后会得到四个工具,位于/usr/local/bin/下面

    [root@bogon mha4mysql-node-0.58]# cd /usr/local/bin/
    [root@bogon bin]# ll | grep log
    -r-xr-xr-x  1 root root 17639 6月  27 22:57 apply_diff_relay_logs
    -r-xr-xr-x  1 root root  4807 6月  27 22:57 filter_mysqlbinlog
    -r-xr-xr-x  1 root root  8337 6月  27 22:57 purge_relay_logs
    -r-xr-xr-x  1 root root  7525 6月  27 22:57 save_binary_logs
    [root@bogon bin]#
    
  4. 安装 MHA Manager 组件

    manager工具包只需要安装在一台机器上,可以是单独的服务器,也可以是集群中任一节点,这里安装在单独的104机器上,安装过程与node工具包一致

    # 将mha4mysql-manager-0.58.tar.gz压缩包上传到这
    tar -zxvf mha4mysql-manager-0.58.tar.gz
    cd mha4mysql-manager-0.58
    perl Makefile.PL
    make && make install
    

    安装完成后在 /usr/local/bin/ 下面可以看到相关的工具

    [root@bogon mha4mysql-manager-0.58]# cd /usr/local/bin/
    [root@bogon bin]# ll | grep master
    -r-xr-xr-x  1 root root  1995 6月  27 23:14 masterha_check_repl
    -r-xr-xr-x  1 root root  1779 6月  27 23:14 masterha_check_ssh
    -r-xr-xr-x  1 root root  1865 6月  27 23:14 masterha_check_status
    -r-xr-xr-x  1 root root  3201 6月  27 23:14 masterha_conf_host
    -r-xr-xr-x  1 root root  2517 6月  27 23:14 masterha_manager
    -r-xr-xr-x  1 root root  2165 6月  27 23:14 masterha_master_monitor
    -r-xr-xr-x  1 root root  2373 6月  27 23:14 masterha_master_switch
    -r-xr-xr-x  1 root root  5172 6月  27 23:14 masterha_secondary_check
    -r-xr-xr-x  1 root root  1739 6月  27 23:14 masterha_stop
    [root@bogon bin]#
    
  5. MHA Manage 机器上需要做的一些配置

    # 创建MHA配置文件目录
    mkdir /etc/mha
    # 创建MHA脚本目录
    mkdir /etc/mha/scripts
    # 创建MHA日志目录
    mkdir /var/log/mha/
    # 创建日志目录(app1是自定义的,因为manager可以同时管理多个集群,所以这里取了这个名)
    mkdir -p /var/log/mha/app1
    # 创建日志文件
    touch /var/log/mha/app1/manager.log
    

    创建第一个配置文件,这个配置主要是一个mysql主从的名单。 candidate_master=1的意思是是否能提升为master,可以不加。

    vi /etc/mha/app1.cnf
    
    # 加入这些内容
    [server default]
    manager_workdir=/var/log/mha/app1
    manager_log=/var/log/mha/app1/manager.log
    [server1]
    hostname=192.168.241.101
    port=3306
    [server2]
    hostname=192.168.241.102
    port=3306
    candidate_master=1
    [server3]
    hostname=192.168.241.103
    port=3306
    

    创建第二个配置文件

    vi /etc/masterha_default.cnf
    
    # 加入这些内容
    [server default]
    user=repl
    password=123456
    repl_user=repl
    repl_password=123456
    ssh_user=root
    ping_interval=1
    master_binlog_dir=/www/server/data/
    manager_workdir=/var/log/mha/app1
    manager_log=/var/log/mha/app1/manager.log
    master_ip_failover_script="/etc/mha/scripts/master_ip_failover"
    master_ip_online_change_script="/etc/mha/scripts/master_ip_online_change"
    report_script="/etc/mha/scripts/send_report"
    remote_workdir=/tmp
    secondary_check_script= /usr/local/bin/masterha_secondary_check -s 192.168.241.101 -s 192.168.241.102 -s 192.168.241.103
    shutdown_script=""
    

    配置参数详解

    user=repl:设置监控mysql的用户

    password=123456:设置监控mysql的用户密码,需要授权能够在manager节点远程登录

    repl_user=repl:设置mysql中用于复制的用户

    repl_password=123456:设置mysql中用于复制的用户密码

    ssh_user=root:设置ssh的登录用户名

    ping_interval=1:设置监控主库,发送ping包的时间间隔,默认是3秒,尝试三次没有回应的时候自动进行railover

    master_binlog_dir=/www/server/data/:设置master 保存binlog的位置,以便MHA可以找到master的日志

    manager_workdir=/var/log/mha/app1:设置manager的工作目录

    manager_log=/var/log/mha/app1/manager.log:设置manager的日志文件

    master_ip_failover_script="/etc/mha/scripts/master_ip_failover":设置自动failover时候的切换脚本 master_ip_online_change_script="/etc/mha/scripts/master_ip_online_change":设置手动切换时候的切换脚本

    report_script=/usr/local/send_report:设置发生切换后发送的报警的脚本

    remote_workdir=/tmp:设置远端mysql在发生切换时binlog的保存位置

    shutdown_script="":设置故障发生后关闭故障主机脚本(该脚本的主要作用是关闭主机防止发生脑裂,这里没有使用)

    candidate_master=1:在从节点下设置,设置当前节点为候选的master

    slave check_repl_delay=0 :在节点配置下设置,默认情况下如果一个slave落后master 100M的relay logs的话,MHA将不会选择该slave作为一个新 的master;这个选项对于对于设置了candidate_master=1的主机非常有用

    脚本配置

    vi /etc/mha/scripts/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.241.105';
    my $key = '0';
    my $ssh_start_vip = "ifconfig ens32:0 192.168.241.105 netmask 255.255.255.0 up";
    my $ssh_stop_vip = "/sbin/ifconfig ens32:$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";
    }
    

    注意:这里的变量 vip和key 要换成自己的;如果网卡类型不是ens32的,也要把文中的ens32换成自己的

    最后给这个脚本增加执行权限

    chmod +x /etc/mha/scripts/master_ip_failover
    
  6. 通过 masterha_check_ssh 命令验证ssh 信任登录是否成功

    [root@bogon bin]# masterha_check_ssh --conf=/etc/mha/app1.cnf
    Sat Jul  3 01:22:18 2021 - [info] Reading default configuration from /etc/masterha_default.cnf..
    Sat Jul  3 01:22:18 2021 - [info] Reading application default configuration from /etc/mha/app1.cnf..
    Sat Jul  3 01:22:18 2021 - [info] Reading server configuration from /etc/mha/app1.cnf..
    Sat Jul  3 01:22:18 2021 - [info] Starting SSH connection tests..
    Sat Jul  3 01:22:19 2021 - [debug] 
    Sat Jul  3 01:22:18 2021 - [debug]  Connecting via SSH from root@192.168.241.101(192.168.241.101:22) to root@192.168.241.102(192.168.241.102:22)..
    Sat Jul  3 01:22:19 2021 - [debug]   ok.
    Sat Jul  3 01:22:19 2021 - [debug]  Connecting via SSH from root@192.168.241.101(192.168.241.101:22) to root@192.168.241.103(192.168.241.103:22)..
    Sat Jul  3 01:22:19 2021 - [debug]   ok.
    Sat Jul  3 01:22:20 2021 - [debug] 
    Sat Jul  3 01:22:19 2021 - [debug]  Connecting via SSH from root@192.168.241.102(192.168.241.102:22) to root@192.168.241.101(192.168.241.101:22)..
    Sat Jul  3 01:22:19 2021 - [debug]   ok.
    Sat Jul  3 01:22:19 2021 - [debug]  Connecting via SSH from root@192.168.241.102(192.168.241.102:22) to root@192.168.241.103(192.168.241.103:22)..
    Warning: Permanently added '192.168.241.103' (ECDSA) to the list of known hosts.
    Sat Jul  3 01:22:20 2021 - [debug]   ok.
    Sat Jul  3 01:22:21 2021 - [debug] 
    Sat Jul  3 01:22:19 2021 - [debug]  Connecting via SSH from root@192.168.241.103(192.168.241.103:22) to root@192.168.241.101(192.168.241.101:22)..
    Sat Jul  3 01:22:20 2021 - [debug]   ok.
    Sat Jul  3 01:22:20 2021 - [debug]  Connecting via SSH from root@192.168.241.103(192.168.241.103:22) to root@192.168.241.102(192.168.241.102:22)..
    Warning: Permanently added '192.168.241.102' (ECDSA) to the list of known hosts.
    Sat Jul  3 01:22:20 2021 - [debug]   ok.
    Sat Jul  3 01:22:21 2021 - [info] All SSH connection tests passed successfully.
    [root@localhost bin]#
    

    显示这样,表示成功

  7. 通过 masterha_check_repl 命令验证 MySQL主从复制是否成功

    这里出现的问题可能有很多,有各种各样的坑,我这里只遇到了下边这一个。如果遇到不同的错误直接百度,网上有很多讲报错的文章

    1、错误信息:Can't exec "mysqlbinlog": 没有那个文件或目录 at /usr/local/share/perl5/MHA/BinlogManager.pm line 106.

    2、解决方案:在三台MySQL机器上添加mysqlbinlog软链接(mysqlbinlog的路径根据自己实际的来)

    ln -s /www/server/mysql/bin/mysqlbinlog /usr/local/bin/mysqlbinlog

    当最后出现这个提示,则表示成功

    MySQL Replication Health is OK.
    
  8. 启动 MHA

    初次使用的时候,需要先在master节点上添加vip,以后就不需要了

    ifconfig ens32:0 192.168.232.105 netmask 255.255.255.0 up
    

    在104机器上执行启动manager

    masterha_manager --conf=/etc/mha/app1.cnf --remove_dead_master_conf --ignore_last_failover < /dev/null > /var/log/mha/app1/manager.log
    

    检查 MHA 状态

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

    关闭 MHA

    masterha_stop --conf=/etc/mha/app1.cnf
    

    启动成功后就可以进行模拟宕机测试了

四、模拟宕机测试

现在的架构是 :

101:主节点

102:从节点1

103:从节点2

手动将101的MySQL主节点关闭,在102的节点上查看VIP,发现配置的VIP:192.168.232.105已经从101节点漂移到102节点了。

[root@localhost mha4mysql-node-0.58]# ip a | grep 241
    inet 192.168.241.102/24 brd 192.168.241.255 scope global noprefixroute ens32
    inet 192.168.241.105/24 brd 192.168.241.255 scope global secondary ens32:0
[root@localhost mha4mysql-node-0.58]#

然后在103的节点上可以看到主节点确实已经变成了 102

mysql> show slave status \G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 192.168.241.102
                  Master_User: repl
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000012
          Read_Master_Log_Pos: 154
          ......

到此,MHA 搭建大功告成啦!

五、总结

MHA 的切换过程,共包括以下的步骤:

  1. 配置文件检查阶段,这个阶段会检查整个集群配置文件配置
  2. 宕机的 master 处理,这个阶段包括虚拟 ip 摘除操作,主机关机操作(由于没有定义power_manager脚本,不会关机)
  3. 复制 dead maste 和最新 slave 相差的 relay log,并保存到 MHA Manger 具体的目录下
  4. 识别含有最新更新的 slave
  5. 应用从 master 保存的二进制日志事件(binlog events)(这点信息对于将故障master修复后加入集群很重要)
  6. 提升一个 slave 为新的 master 进行复制
  7. 使其他的 slave 连接新的 master 进行复制

最后说明一点,宕机的节点,重启后由于MySQL机制问题不会自动加入到集群中,需要我们手动加入。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,911评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,014评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 142,129评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,283评论 1 264
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,159评论 4 357
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,161评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,565评论 3 382
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,251评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,531评论 1 292
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,619评论 2 310
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,383评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,255评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,624评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,916评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,199评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,553评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,756评论 2 335

推荐阅读更多精彩内容