MHA高可用数据库集群部署及模拟故障

一、概述
    Master High Availability(MHA)优秀的作为MySQL高可用性环境下故障切换和主从角色提升的高可用软件
二、发挥过程
    在MySQL故障切换过程中,MHA能做到在0~30秒之内自动完成数据库的主从故障切换操作
    在进行故障切换的过程中,MHA能在最大程度上保证数据的一致性。
三、组成
    MHA Manager(管理节点)
    MHA Node(数据节点)
四、原理
    MHA Node运行在每台MySQL服务器及Manager服务器上
    MHA Manager会定时探测集群中的master节点
    当master出现故障时,它可以自动将拥有最新数据的slave提升为新的master
    将所有其他的slave重新指向新提升的master
    通过检测二进制文件的时间节点和操作ID,从数据库谁最新,谁就变成主
五、条件
    支持一主多从的架构,要搭建MHA,要求一个MySQL复制集群中必须最少有三台数据库服务器
    一主二从,即一台充当master,一台充当备用master,另外一台充当从库
六、架构
    一个MHA Manger,检测多个主数据库,主数据库下有多个从数据库
    每一个主数据库和从数据库称之为复制组
    当主数据库坏掉,检测从谁最新成为主
七、工作流程
    从宕机崩溃的master上尝试保存二进制日志事件(binlog events)
    识别含有最新更新的slave服务器
    应用差异的中继日志(relay log)到其他的slave
    应用从master保存的二进制日志事件(binlog events)
    提升一个slave为新的master服务器
    将其他的slave连接指向新的master进行主从复制
八、工具介绍
    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线程)
                    从变成主之后要清除,否则会影响SQL线程,主服务不需要
    (注意:为了尽可能的减少主库硬件损坏宕机造成的数据丢失,因此在配置MHA的同时建议配置成MySQL 5.5的半同步复制;不是必须)
九、环境说明
    所有操作系统均为centos 7.x 64bit
    至少五台主机,一主三从一Manger
    三从的一从指定为主的备胎,当主坏掉,他顶上,但默认情况还是从的角色
十、安装MHA node(五台主机)
    配置所有主机名称

        hostnamectl set-hostname node1
        hostnamectl set-hostname node2
        hostnamectl set-hostname node3
        hostnamectl set-hostname node4
        hostnamectl set-hostname node5


    在所有主机的/etc/hosts中写入每台主机的IP及主机名称

        cat << END >> /etc/hosts
        192.168.1.221 node1
        192.168.1.222 node2
        192.168.1.223 node3
        192.168.1.224 node4
        192.168.1.225 node5
        END


    配置SSH密钥对验证
      

 所有主机获取密钥    ssh-keygen -t rsa    
        复制其他4台主机密钥到代理服务器node5(Manger)         ssh-copy-id -i .ssh/id_rsa.pub root@node5


        将node5的密钥文件发送给其他4台主机

scp .ssh/authorized_keys root@node2:.ssh/
scp .ssh/authorized_keys root@node3:.ssh/
scp .ssh/authorized_keys root@node4:.ssh/
scp .ssh/authorized_keys root@node5:.ssh/


        测试免密登录(每台主机都测,第一次连接的时候需要输入yes用来获取信任)

ssh node1
ssh node2
ssh node3
ssh node4
ssh node5


    所有主机安装MHA nade的相关依赖包

yum install -y perl-DBD-MySQL.x86_64 perl-DBI.x86_64 perl-CPAN perl-ExtUtils-CBuilder perl-ExtUtils-MakeMaker

rz    #将MHA node源码包传输到每台主机

 tar xf mha4mysql-node-0.56.tar.gz    #解压

 cd mha4mysql-node-0.56/        #切换到此目录

 perl Makefile.PL            #用perl语言编译文件
                            #生成Makefile文件

make && make install        #编译安装

ll /usr/local/bin/            #MHA Node安装完后会在 /usr/local/bin生成以下脚本;里面有4个命令文件


十一、在node5(manger)主机上安装MHA manger
    安装MHA manger依赖的perl模块

 yum install -y perl perl-Log-Dispatch perl-Parallel-ForkManager perl-DBD-MySQL perl-DBI perl-Time-HiRes

rz    #将MHA manger依赖源码包传输到node5主机

rpm ivh perl-Config-Tiny-2.14-7.el7.noarch.rpm        #用rpm安装源码包

rz    #将MHA manger源码包传输到node5主机

tar xf mha4mysql-manager-0.56.tar.gz         #解压

cd mha4mysql-manager-0.56/        #切换到此目录下

perl Makefile.PL                #用perl语言编译文件
                                #生成Makefile文件

make && make install            #编译安装

ll /usr/local/bin/                #此时这个文件下有13个命令文件


十二、配置主从复制(数据库主机上安装)

    yum -y install mariadb mariadb-server mariadb-devel        #所有服务器安装MySQL数据库
    systemctl start mariadb                    #所有服务器启动服务
    mysqladmin -u root password 123456                #所有服务器更改初始密码


    node1(主)配置

vim /etc/my.cnf
   server-id = 1                #主id为1;其他为从
   log-bin=master-bin
   log-slave-updates=true            
   relay_log_purge=0                 #禁止 SQL 线程在执行完一个 relay log 后自动将其删除


    node2(从)配置

vim /etc/my.cnf
   server-id = 2                #主id为1;其他为从
   log-bin=master-bin
   log-slave-updates=true            #从库做为其他从库的主库时 log-slave-updates参数是必须要添加的,因为从库要作为其他从库的主库,必须添加该参数
   relay_log_purge=0                 #禁止 SQL 线程在执行完一个 relay log 后自动将其删除


    node3(从)配置

vim /etc/my.cnf
    server-id=3                #主id为1;其他为从
    log-bin=mysql-bin
    relay-log=slave-relay-bin
    log-slave-updates=true
    relay_log_purge=0                #禁止 SQL 线程在执行完一个 relay log 后自动将其删除


    node4(从)配置

vim /etc/my.cnf
    server-id=4                #主id为1;其他为从
    log-bin=mysql-bin
    relay-log=slave-relay-bin
    log-slave-updates=true
    relay_log_purge=0                #禁止 SQL 线程在执行完一个 relay log 后自动将其删除


    systectl restart mariadb                    #所有数据库主机重启服务

mysqldump --master-data=2 --single-transaction -R --triggers -A > all.sql    #将旧数据备份(若没有旧数据则可略过此步)
        --master-data=2                            #备份时刻记录master的Binlog位置和Position
        --single-transaction                        #获取一致性快照
        -R                                #备份存储过程和函数
        -triggres                           #备份触发器
        -A                                #备份所有的库
    scp all.sql 192.168.1.222:/tmp/                    #远程复制到从服务器上


    所有数据库授权

grant replication slave on *.* to 'repl'@'192.168.1.%' identified by '123456';
flush privileges;                        #刷新权限


    在node1(主)服务器上查看主状态

show master status;                    #查看二进制文件名及文件位置


    所有从服务器上指定主

stop slave;                        #停止从服务

change master to master_host='主库IP地址',master_user='repl',master_password='123456',master_log_file='二进制文件名',master_log_pos=二进制文件位置;        #指定主

start slave;                        #开启从服务

show slave status\G                        #查看从服务器状态

set global read_only=1;                    #所有从服务器设置read_only状态;从库对外只提供读服务,只所以没有写进mysql配置文件,是因为随时server02会提升为master


    创建监控用户(所有数据库)

grant all privileges on *.* to 'root'@'192.168.1.%' identified  by '123456';
flush privileges;                        #刷新权限


    所有数据库为自己的主机授权

    (node1)
        grant all privileges on *.* to 'root'@'node1'  identified  by '123456';
        flush privileges;
    (node2)
        grant all privileges on *.* to 'root'@'node2'  identified  by '123456';
        flush privileges;
    (node3)
        grant all privileges on *.* to 'root'@'node3'  identified  by '123456';
        flush privileges;
    (node4)
        grant all privileges on *.* to 'root'@'node4'  identified  by '123456';
        flush privileges;
        


十三、配置MHA环境
    mkdir /etc/masterha        #创建配置目录
    cp mha4mysql-manager-0.56/samples/conf/app1.cnf /etc/masterha        #复制模板文件到该配置目录下(软件包解压后的目录里面有样例配置文件)

    vim /etc/masterha/app1.cnf        #修改配置文件
        [server default]
        #设置manager的工作日志
        manager_workdir=/var/log/masterha/app1 
        #设置manager的日志,这两条都是默认存在的
        manager_log=/var/log/masterha/app1/manager.log

        #设置master默认保存binlog的位置,以便MHA可以找到master日志
        master_binlog_dir=/var/lib/mysql

        #设置自动failover时候的切换脚本
        master_ip_failover_script= /usr/local/bin/master_ip_failover

        #设置mysql中root用户的密码
        password=123456
        user=root
        #ping包的时间间隔
        ping_interval=1
        #设置远端mysql在发生切换时保存binlog的具体位置
        remote_workdir=/tmp
        #设置复制用户的密码和用户名
        repl_password=123456
        repl_user=repl

        [server1]
        hostname=server01
        port=3306

        [server2]
        hostname=server02
        candidate_master=1        #候选人
        port=3306
        check_repl_delay=0

        [server3]
        hostname=server03
        port=3306

        [server4]
        hostname=server04
        port=3306

    vim /usr/local/bin/master_ip_failover            #配置故障转移脚本(设置vip,修改网卡名)
        #!/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.1.100';                  #vip地址设置为没有在使用的IP地址
        my $key = "1";     
        my $ssh_start_vip = "/sbin/ifconfig ens33:$key $vip";        #网卡名一般为ens33(根据实际情况更改)
        my $ssh_stop_vip = "/sbin/ifconfig ens33:$key down"; 
        $ssh_user = "root"; 
        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" ) { 
        # $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 "Disabling the VIP on old master: $orig_master_host \n"; 
        # &stop_vip(); 
        # $exit_code = 0; 
        #}; 
        eval { 
        print "Disabling the VIP on old master: $orig_master_host \n"; 
        #my $ping=`ping -c 1 10.0.0.13 | grep "packet loss" | awk -F',' '{print $3}' | awk '{print $1}'`; 
        #if ( $ping le "90.0%"&& $ping gt "0.0%" ){ 
        #$exit_code = 0; 
        #} 
        #else { 
        &stop_vip(); 
        # updating global catalog, etc 
        $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 "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"; 
        `ssh $ssh_user\@$orig_master_ip \" $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 $ssh_user\@$new_master_host \" $ssh_start_vip \"`; 
        } 
        # A simple system call that disable the VIP on the old_master 
        sub stop_vip() { 
        `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"; }

chmod +x /usr/local/bin/master_ip_failover        #给该配置文件权限
masterha_check_ssh --conf=/etc/masterha/app1.cnf    #检查MHA ssh通信状态
                                                    #返回 successfully表示没有问题
masterha_check_repl --conf=/etc/masterha/app1.cnf    #检查整个集群的状态
                                                     #返回ok表示没有问题(note ok为配置文件有错误)
masterha_check_status --conf=/etc/masterha/app1.cnf    #检查manager状态
                                                       #如果正常会显示"PING_OK";NOT_RUNNING",代表MHA监控没有开启

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

masterha_stop --conf=/etc/masterha/app1.cnf        #关闭manager监控


十四、测试
    ip a | grep ens33        #在主数据库(node1)服务器上用此命令查看网卡以获得vip地址
    systemctl stop mariadb    #模拟故障(停止主服务器服务)

    在node5(管理节点上查看配置文件)
 

vim /etc/masterha/app1.cnf

                在这个文件中若node1消失,则说明监控系统起到作用

                若没有消失则是node5系统出现问题或配置文件有问题;逐一排查

  在node3(从节点)上查看数据库状态

show slave status \G

                查看主服务器的IP是否转成node2的IP地址,若成功转成node2地址则说明监控起到作用

                若没显示node2IP地址,则说明转换失败,要逐一排查错误

       主服务器修复并开启服务

node1

systemctl start mariadb;            #开启服务
mysql -u登录数据库的用户名 -p用户密码        #登录数据库
grant all privileges on *.* to 'root'@'node1 ' identified  by '123456';            #给自己授权
flush privileges;        #刷新权限
change master to master_host='备用数据库IP',master_user='repl',master_password='123456';        #指定备用数据库
start slave;        #开启从服务
show slave status \G        #查看服务器状态

node5

vim /etc/masterha/app1.cnf            #将node1信息添加到配置文件中

[node1]
hostname=server02
port=3306

masterha_check_ssh --conf=/etc/masterha/app1.cnf        #检查远程连接是否正常
masterha_check_repl --conf=/etc/masterha/app1.cnf        #查看集群是否正常
nohup masterha_manager --conf=/etc/masterha/app1.cnf --remove_dead_master_conf --ignore_last_failover< /dev/null >/var/log/masterha/app1/manager.log 2>&1 &            #开启监控
masterha_check_status --conf=/etc/masterha/app1.cnf        #查看监控状态是否正常

现在node1(主服务器)是node2(备用主)的从,也是node2的备用主;只要node2一宕机,node1就会重新成为主,node2又进行上述步骤恢复备用主。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱笑的男孩0522

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值