MySQL MHA高可用

MHA简介

MySQL MHA(Master High Availability)是一套为MySQL数据库设计的高可用性解决方案,旨在解决MySQL单点故障问题。以下是关于MySQL MHA的简介:

1. 功能概述

  • 自动化主服务器监控和故障转移:MHA可以监控MySQL主服务器的状态,并在检测到故障时自动执行故障转移操作,确保数据的高可用性。
  • 主服务器故障转移的快速性:故障切换过程中,MHA能在0-30秒内自动完成故障切换操作,大大减少了停机时间。
  • 数据一致性保证:MHA在故障切换过程中能最大程度上保证数据的一致性,使用半同步复制等技术降低数据丢失的风险。
  • 支持多种故障转移模式:包括自动化主服务器监控和故障转移、交互式(手动启动的)主故障转移以及在线切换主机等。

2. 组成结构

  • MHA Manager(管理节点):可以单独部署在一台独立的机器上,用于管理多个master-slave集群;也可以部署在一台slave节点上。MHA Manager会定时探测集群中的master节点,当master出现故障时,可以自动将最新数据的slave提升为新的master,并将其他slave重新指向新的master。
  • MHA Node(数据节点):运行在每台MySQL服务器上,是MHA架构中的数据库节点。

3. 特点

  • 快速性:故障切换速度快,通常在10-30秒内完成。
  • 数据一致性:使用半同步复制等技术,确保数据在故障切换过程中的一致性。
  • 灵活性:支持一主多从架构,最少三台服务,即一主两从。
  • 易用性:无需修改当前的MySQL设置,无需增加大量服务器,无性能损耗,易于安装和使用。

4. 工作原理

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

MHA Manaqer(管理节点)

  • 管理所有数据库服务器

  • 可以单独部署在一台独立的机器上

  • 也可以部署在某台数据库服务器上

MHA Node(数据节点)

  • 存储数据的MySQL服务器
  • 运行在每台MySQL服务器上

MHA安装配置

环境准备

1、配置hosts
2、关闭防火墙
3、禁用SELinux
4、配置ssh互相无密连接

主机 角色
nnode1/192.168.126.21 mha4mysql-manager、mha4mysql-node
dnode1/192.168.126.22 mha4mysql-node
dnode2/192.168.126.23 mha4mysql-node

配置一主二从

yum install -y mariadb-server
systemctl start mariadb.service

主库配置

[mysqld]
server_id=21
log-bin=master
skip_name_resolve=ON
#禁止自动删除中继日志
relay_log_purge=0
#启用半同步模块
plugin-load="rpl_semi_sync_master=semisync_master.so;rpl_semi_sync_slave=semisync_slave.so"
rpl_semi_sync_master_enabled=1
rpl_semi_sync_slave_enabled=1


systemctl restart mariadb.service
MariaDB [(none)]> grant replication slave on *.* to repluser@"%" identified by "123456";
Query OK, 0 rows affected (0.00 sec)

MariaDB [(none)]> flush privileges;
Query OK, 0 rows affected (0.00 sec)

MariaDB [(none)]> show master status;
+---------------+----------+--------------+------------------+
| File          | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+---------------+----------+--------------+------------------+
| master.000001 |      464 |              |                  |
+---------------+----------+--------------+------------------+

两个从库配置,修改log-bin的文件名和server_id,不能一样

[mysqld]
server_id=22
log-bin=master2
skip_name_resolve=ON
#禁止自动删除中继日志
relay_log_purge=0
#启用半同步模块
plugin-load="rpl_semi_sync_master=semisync_master.so;rpl_semi_sync_slave=semisync_slave.so"
rpl_semi_sync_master_enabled=1
rpl_semi_sync_slave_enabled=1


systemctl restart mariadb.service
 change master to 
 master_host="192.168.126.21",
 master_user="repluser",
 master_password="123456",
 master_log_file="master.000001",
 master_log_pos=464;

 start slave;

 MariaDB [(none)]> show slave status \G;
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 192.168.126.21
                  Master_User: repluser
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: master.000001
          Read_Master_Log_Pos: 464
               Relay_Log_File: mariadb-relay-bin.000002
                Relay_Log_Pos: 526
        Relay_Master_Log_File: master.000001
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes

MariaDB [(none)]> grant replication slave on *.* to repluser@"%" identified by "123456";
Query OK, 0 rows affected (0.00 sec)

MariaDB [(none)]> flush privileges;
Query OK, 0 rows affected (0.00 sec)

主库上配置root权限,从库自动同步

 grant all on *.* to root@"%" identified by "123456";
 grant all on *.* to root@"nnode1" identified by "123456";
 grant all on *.* to root@"dnode1" identified by "123456";
 grant all on *.* to root@"dnode2" identified by "123456";
 flush privileges;

MHA安装

manager节点需要安装mha4mysql-manager和mha4mysql-node,要先装node

wget https://github.com/yoshinorim/mha4mysql-manager/releases/download/v0.58/mha4mysql-manager-0.58-0.el7.centos.noarch.rpm
wget https://github.com/yoshinorim/mha4mysql-node/releases/download/v0.58/mha4mysql-node-0.58-0.el7.centos.noarch.rpm

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

node节点安装mha4mysql-node

wget https://github.com/yoshinorim/mha4mysql-node/releases/download/v0.58/mha4mysql-node-0.58-0.el7.centos.noarch.rpm
yum install -y mha4mysql-node-0.58-0.el7.centos.noarch.rpm
已安装:
  mha4mysql-node.noarch 0:0.58-0.el7.centos

作为依赖被安装:
  perl-Compress-Raw-Bzip2.x86_64 0:2.061-3.el7           perl-Compress-Raw-Zlib.x86_64 1:2.061-4.el7           perl-DBD-MySQL.x86_64 0:4.023-6.el7
  perl-DBI.x86_64 0:1.627-4.el7                          perl-Data-Dumper.x86_64 0:2.145-3.el7                 perl-IO-Compress.noarch 0:2.061-2.el7
  perl-Net-Daemon.noarch 0:0.48-5.el7                    perl-PlRPC.noarch 0:0.2020-14.el7
 node节点
 mkdir /etc/mhamysql/mha-node -p
 manager节点
 mkdir /etc/mhamysql/mha -p

master_ip_failover文件用来在master出故障时执行,实现高可用自动切换vip

新建master_ip_failover文件,修改以下内容的ip和网卡,ip改为需要的vip,如果多台机器直接的网卡名称不统一,有两种方式,一个是改脚本,二是把网卡名称修改成统一

cat >/etc/mhamysql/master_ip_failover<<'EOF'
#!/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.126.100/24';
my $key = '1';
my $ssh_start_vip = "/sbin/ifconfig ens33:$key $vip";
my $ssh_stop_vip = "/sbin/ifconfig ens33:$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 \"`;
}
# 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";
}
EOF

添加可执行权限

chmod +x /etc/mhamysql/master_ip_failover

添加MHA配置文件/etc/mhamysql/mysql_mha.cnf

#编写配置文件
cat > /etc/mhamysql/mysql_mha.cnf<<EOF

[server default]
#指定mha的工作目录
manager_workdir=/etc/mhamysql/mha
#指定管理日志路径
manager_log=/etc/mhamysql/manager.log

#指定一个脚本,该脚本实现了在主从切换之后,将虚拟ip漂移到新的master上
master_ip_failover_script=/etc/mhamysql/master_ip_failover
#指定mha在远程节点上的工作目录
remote_workdir=/etc/mhamysql/mha-node


#ssh的用户和端口
ssh_port=22
ssh_user=root

#指定主从复制的mysql用户和密码
repl_user=repluser
repl_password=123456

#mha访问数据库的账号与密码
user=root
password=123456
port=3306


#指定master节点存放binlog的日志文件的目录,默认是在/var/lib/mysql
master_binlog_dir=/var/lib/mysql


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

#指定检查的从服务器IP地址.有几个,就用-s选项加几个
secondary_check_script=/usr/bin/masterha_secondary_check -s 192.168.126.22 -s 192.168.126.23
#用于故障切换的时候发送邮件提醒
#report_script=/data1/mysql-mha/send_mail

[server1]
hostname=192.168.126.21
candidate_master=1
check_repl_delay=0

[server2]
hostname=192.168.126.22
candidate_master=1
check_repl_delay=0

[server3]
hostname=192.168.126.23
candidate_master=1
check_repl_delay=0
EOF
#设置为候选master,发生主从切换以后将会将此从库提升为主库,即使这个从库不是集群中最新的slave,no_master=1正好相反
candidate_master=1
#默认情况下如果一个slave落后master 超过100M的relay logs的话,MHA将不会选择该slave作为一个新的master, 因为对于这个slave的恢复需要花费很长时间;通过设置check_repl_delay=0,MHA触发切换在选择一个新的master的时候将会忽略复制延时,这个参数对于设置了candidate_master=1的主机非常有用,因为这个候选主在切换的过程中一定是新的master

在master上配置vip

ifconfig ens33:1 192.168.126.100/24
[root@nnode1 ~]# ifconfig ens33:1
ens33:1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.126.100  netmask 255.255.255.0  broadcast 192.168.126.255
        ether 00:0c:29:13:25:db  txqueuelen 1000  (Ethernet)

在manager 节点测试ssh 无密认证

 masterha_check_ssh   -conf=/etc/mhamysql/mysql_mha.cnf

《MySQL MHA高可用》

在manager 节点上测试mysql主从情况

 masterha_check_repl -conf=/etc/mhamysql/mysql_mha.cnf

运行以上命令报错的话,所有节点修改vim /usr/share/perl5/vendor_perl/MHA/SlaveUtil.pm文件,mariadb没有super_read_only变量需要修改,看下面标题错误及解决

《MySQL MHA高可用》

启动MHA

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

高可用测试

停止nnode1 master节点,再查看主从状态

MariaDB [(none)]> show slave status \G;
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 192.168.126.21

[root@nnode1 ~]# systemctl stop mariadb.service

dnode2查看主从状态

MariaDB [(none)]> show slave status \G;
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 192.168.126.22
可以看到mysql_mha.cnf自动删除master server1的配置
[root@nnode1 ~]# cat /etc/mhamysql/mysql_mha.cnf自动删除master配置
[server default]
manager_log=/etc/mhamysql/manager.log
manager_workdir=/etc/mhamysql/mha
master_binlog_dir=/var/lib/mysql
master_ip_failover_script=/etc/mhamysql/master_ip_failover
password=123456
ping_interval=1
port=3306
remote_workdir=/etc/mhamysql/mha-node
repl_password=123456
repl_user=repluser
secondary_check_script=/usr/bin/masterha_secondary_check -s 192.168.126.22 -s 192.168.126.23
ssh_port=22
ssh_user=root
user=root

[server2]
candidate_master=1
check_repl_delay=0
hostname=192.168.126.22

[server3]
candidate_master=1
check_repl_delay=0
hostname=192.168.126.23

ip转移至新master dnode1处

[root@dnode1 ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet 192.168.126.150/32 brd 192.168.126.150 scope global lo:1
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:0c:29:2e:cd:19 brd ff:ff:ff:ff:ff:ff
    inet 192.168.126.22/24 brd 192.168.126.255 scope global ens33
       valid_lft forever preferred_lft forever
    inet 192.168.126.100/24 brd 192.168.126.255 scope global secondary ens33:1
       valid_lft forever preferred_lft forever
    inet6 fe80::20c:29ff:fe2e:cd19/64 scope link
       valid_lft forever preferred_lft forever

故障修复

在当前主节点dnode1查看master状态

MariaDB [(none)]> show master status;
+----------------+----------+--------------+------------------+
| File           | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+----------------+----------+--------------+------------------+
| master2.000004 |      245 |              |                  |
+----------------+----------+--------------+------------------+
1 row in set (0.00 sec)

在原master服务器上执行主从同步,这里没有进行数据同步操作,生产环境要注意

[root@nnode1 ~]# systemctl start mariadb.service
 change master to       
 master_host="192.168.126.22",
 master_user="repluser",
 master_password="123456",
 master_log_file="master2.000004",
 master_log_pos=245;

 start slave;

 show slave status\G

修改mha配置文件,重新添加原master配置

[server1]
hostname=192.168.126.21
candidate_master=1
check_repl_delay=0

测试主从状态

masterha_check_repl -conf=/etc/mhamysql/mysql_mha.cnf

再次启动高可用服务

nohup masterha_manager \
--conf=/etc/mhamysql/mysql_mha.cnf \
--remove_dead_master_conf \
--ignore_last_failover < /dev/null > /var/log/mha_manager.log 2>&1 &

错误及解决

Unknown system variable ‘super_read_only’

Checking if super_read_only is defined and turned on..DBD::mysql::st execute failed: Unknown system variable 'super_read_only' at /usr/share/perl5/vendor_perl/MHA/SlaveUtil.pm line 245. Sat Jun 29 12:36:26 2024 - [error][/usr/share/perl5/vendor_perl/MHA/MasterMonitor.pm, ln208] Slaves settings check failed! Sat Jun 29 12:36:26 2024 - [error][/usr/share/perl5/vendor_perl/MHA/MasterMonitor.pm, ln416] Slave configuration failed. Sat Jun 29 12:36:26 2024 - [error][/usr/share/perl5/vendor_perl/MHA/MasterMonitor.pm, ln427] Error happened on checking configurations.  at /usr/bin/masterha_check_repl line 48. Sat Jun 29 12:36:26 2024 - [error][/usr/share/perl5/vendor_perl/MHA/MasterMonitor.pm, ln525] Error happened on monitoring servers. Sat Jun 29 12:36:26 2024 - 
Got exit code 1 (Not master dead).

这个错误表明MHA(MySQL Master High Availability Manager)在尝试检查super_read_only这个系统变量时失败了,因为MySQL服务器报告了一个“Unknown system variable ‘super_read_only’”的错误。这通常意味着你的MySQL服务器版本不支持super_read_only这个系统变量。

修改vim /usr/share/perl5/vendor_perl/MHA/SlaveUtil.pm文件,所有安装MHA的节点都要改

第244行:

my $sth = $dbh->prepare("SELECT \@\@global.super_read_only as Value");
改为

my $sth = $dbh->prepare("SELECT 0 as Value");
第262行:

$dbh->do("SET GLOBAL super_read_only=off;");
这一行注释起来就行了。

第275行:

$dbh->do("SET GLOBAL super_read_only=on;");
改为

$dbh->do("SET GLOBAL read_only=on;");

参考

MySQL高可用实战( MHA) – 大数据老司机 – 博客园 (cnblogs.com)

MHA报错:Checking if super_read_only is defined and turned …Unknown system variable ‘super_read_only‘_super readonly mariadb-CSDN博客

点赞

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注