MySQL MHA 故障切换

一、案例概述

  • 传统的MySQL主从架构存在的问题
    • 单点故障
    • 目前 MySQL 已经成为市场上主流数据库之一,考虑到业务的重要性,MySQL 数据库单点问题已成为企业网站架构中最大的隐患。
    • 随着技术的发展,MHA 的出现就是解决MySQL 单点的问题。
    • 另外随着企业数据量越来越庞大,数据库的压力又成为企业的另一个瓶颈,MySQL 多主多从架构的出现可以减轻 MySQL 本身的压力。

二、案例前置知识点

  • MHA概述
    • 一套优秀的MySQL高可用环境下故障切换和主从复制的软件
    • MySQL故障过程中,MHA能做到0-30秒内自动完成故障切换
  • MHA的组成
    • MHA Manager(管理节点)
    • NGA Node(数据节点)
  • MHA特点
    • 自动故障切换过程中,MHA试图从宕机的主服务器上保存二进制日志,最大程度的保证数据不丢失
    • 使用半同步复制,可以大大降低数据丢失的风险
    • 目前MHA支持一主多从从架构,最少三台服务,即一主两从

三、实验报告

资源环境

主机操作系统IP配置
masterCentOS7192.168.72.1312C4G
slave1CentOS7192.168.72.1322C4G
slave2CentOS7192.168.72.1332C4G
managerCentOS7192.168.72.1342C4G

基础环境

  • 关闭防火墙
systemctl stop firewalld
systemctl disable firewalld
  • 关闭内核安全机制
setenforce 0
sed -i "s/^SELINUX=.*/SELINUX=disabled/g" /etc/selinux/config
  • 修改主机名
hostnamectl set-hostname master
hostnamectl set-hostname slave1
hostnamectl set-hostname slave2
hostnamectl set-hostname amoeba

一、添加 hosts 解析

cat >> /etc/hosts << EOF
192.168.72.131 master
192.168.72.132 slave1
192.168.72.133 slave2
192.168.72.134 manager
EOF

二、搭建 MySQL 主从复制

1、安装 MySQL 数据库

# 上传脚本
[root@master ~]# tar zxf auto-install-mysql57-glibc.tar.gz 
[root@master ~]# cd auto-install-mysql57-glibc
[root@master auto-install-mysql57-glibc]# ls
auto-install-mysql57-glibc.sh  my.cnf  mysql-5.7.28-linux-glibc2.12-x86_64.tar.gz
[root@master auto-install-mysql57-glibc]# ./auto-install-mysql57-glibc.sh 

set password=password('123');

2、配置 master 主服务器

master
# 开启二进制日志
[root@master ~]# vi /etc/my.cnf
[mysqld]
log-bin=master-bin
binlog-format = MIXED
server-id = 1
# 重启 MySQL 服务
[root@master ~]# systemctl restart mysqld

[root@master ~]# ls /usr/local/mysql/data/
auto.cnf         client-key.pem  ib_logfile1        master.err  mysql.sock.lock     server-cert.pem
ca-key.pem       ib_buffer_pool  ibtmp1             master.pid  performance_schema  server-key.pem
ca.pem           ibdata1         master-bin.000001  mysql       private_key.pem     sys
client-cert.pem  ib_logfile0     master-bin.index   mysql.sock  public_key.pem

# 登录 MySQL 程序,给从服务器授权
grant replication slave on *.* to 'myslave'@'192.168.72.%' identified by '123456';

# 刷新权限
flush privileges;


# MySQL 返回了主服务器的二进制日志(binary log)的当前状态 
mysql> show master status;
+-------------------+----------+--------------+------------------+-------------------+
| File              | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+-------------------+----------+--------------+------------------+-------------------+
| master-bin.000001 |      603 |              |                  |                   |
+-------------------+----------+--------------+------------------+-------------------+
1 row in set (0.03 sec)

3、配置 slave 从服务器

slave1
# 开启二进制日志
[root@slave1 ~]# vi /etc/my.cnf 
[mysqld]
log-bin=slave1-bin
binlog-format = MIXED
server-id = 2
# 重启 MySQL 服务
[root@slave1 ~]# systemctl restart mysqld
[root@slave1 ~]# ls /usr/local/mysql/data/
auto.cnf         client-key.pem  ib_logfile1  mysql.sock.lock     server-cert.pem    slave1.err
ca-key.pem       ib_buffer_pool  ibtmp1       performance_schema  server-key.pem     slave1.pid
ca.pem           ibdata1         mysql        private_key.pem     slave1-bin.000001  sys
client-cert.pem  ib_logfile0     mysql.sock   public_key.pem      slave1-bin.index

# MySQL复制环境中用于配置从服务器(slave)以连接到主服务器(master)并开始复制过程
mysql> change master to master_host='192.168.72.131',        # master 主机的IP
    -> master_user='myslave',        # master 主机设置的用户名
    -> master_password='123456',        # master 主机设置的密码
    -> master_log_file='master-bin.000001',
        # master 主机的日志文件
    -> master_log_pos=603;
        # master 主机的偏移量 当前二进制日志的位置
Query OK, 0 rows affected, 2 warnings (0.04 sec)

mysql> start slave;
Query OK, 0 rows affected (0.01 sec)

# 检查从服务器的复制状态
mysql> show slave status\G;
*************************** 1. row ***************************
...... # 省略部分代码
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
                     
...... # 省略部分代码
1 row in set (0.00 sec)

# 如果出现错误,执行重置重新写
# 关闭   
stop slave;
# 重置
reset slave;

# 俩个从节点执行
# 设置从节点为只读
set global read_only=1;
slave2
# 开启二进制日志
[root@slave2 ~]# vi /etc/my.cnf 
[mysqld]
log-bin=slave2-bin
binlog-format = MIXED
server-id = 3
# 重启 MySQL 服务
[root@slave2 ~]# systemctl restart mysqld

[root@slave2 ~]# ls /usr/local/mysql/data/
auto.cnf         client-key.pem  ib_logfile1  mysql.sock.lock     server-cert.pem    slave2.err
ca-key.pem       ib_buffer_pool  ibtmp1       performance_schema  server-key.pem     slave2.pid
ca.pem           ibdata1         mysql        private_key.pem     slave2-bin.000001  sys
client-cert.pem  ib_logfile0     mysql.sock   public_key.pem      slave2-bin.index

# MySQL复制环境中用于配置从服务器(slave)以连接到主服务器(master)并开始复制过程
mysql> change master to master_host='192.168.72.131',        # master 主机的IP
    -> master_user='myslave',        # master 主机设置的用户名
    -> master_password='123456',        # master 主机设置的密码
    -> master_log_file='master-bin.000001',
        # master 主机的日志文件
    -> master_log_pos=603;
        # master 主机的偏移量    当前二进制日志的位置
Query OK, 0 rows affected, 2 warnings (0.04 sec)

mysql> start slave;
Query OK, 0 rows affected (0.01 sec)

# 检查从服务器的复制状态
mysql> show slave status\G;
*************************** 1. row ***************************
...... # 省略部分代码
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
                     
...... # 省略部分代码
1 row in set (0.00 sec)

# 如果出现错误,执行重置重新写
# 关闭   
stop slave;
# 重置
reset slave;
   
#重新执行change

# 俩个从节点执行
# 设置从节点为只读
set global read_only=1;

三、安装 MHA 软件

1、所有节点上都安装 MHA 依赖的环境,首先安装 epel 源。

yum install -y epel-release
yum install -y perl-DBD-MySQL perl-Config-Tiny perl-Log-Dispatch perl-Parallel-ForkManager \
perl-ExtUtils-CBuilder perl-ExtUtils-MakeMaker perl-CPAN

2、所有节点上都安装 node 组件

tar zxf mha4mysql-node-0.57.tar.gz
cd mha4mysql-node-0.57
perl Makefile.PL
make
make install

3、在 MHA-manager 上安装 manager 组件

tar zxf mha4mysql-manager-0.57.tar.gz
cd mha4mysql-manager-0.57
perl Makefile.PL
make
make install

4、manager 安装后在/usr/local/bin 下面会生成几个工具,主要包括:

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

5、 node 安装后也会在/usr/local/bin 下面会生成几个脚本(这些工具通常由 MHA Manager 的脚本触发,无需人为操作)。

save_binary_logs:保存和复制 master 的二进制日志。
apply_diff_relay_logs:识别差异的中继日志事件并将其差异的事件应用于其他的 slave。
filter_mysqlbinlog:去除不必要的 ROLLBACK 事件(MHA 已不再使用这个工具)。
purge_relay_logs:清除中继日志(不会阻塞 SQL 线程)。

四、配置无密码认证

1、在manager上配置到数据库节点的无密码认证

# 一路按回车键
[root@manager ~]# ssh-keygen

# 根据提示输入 yes 和虚拟机的密码
[root@manager ~]# ssh-copy-id master
[root@manager ~]# ssh-copy-id slave1
[root@manager ~]# ssh-copy-id slave2

2、在 master上配置到数据库节点的无密码认证

# 一路按回车键
[root@master ~]# ssh-keygen -t rsa

# 根据提示输入 yes 和虚拟机的密码
[root@master ~]# ssh-copy-id slave1
[root@master ~]# ssh-copy-id slave2

3、在 slave1 上配置到数据库节点的无密码认证

# 一路按回车键
[root@slave1 ~]# ssh-keygen -t rsa

# 根据提示输入 yes 和虚拟机的密码
[root@slave1 ~]# ssh-copy-id master
[root@slave1 ~]# ssh-copy-id slave2

4、在 slave2 上配置到数据库节点的无密码认证

# 一路按回车键
[root@slave2 ~]# ssh-keygen -t rsa

# 根据提示输入 yes 和虚拟机的密码
[root@slave2 ~]# ssh-copy-id master
[root@slave2 ~]# ssh-copy-id slave1

五、配置 MHA

1、在 manager 节点上复制相关脚本到/usr/local/bin 目录

[root@manager ~]# ll /root/mha4mysql-manager-0.57/samples/scripts/
总用量 32
-rwxr-xr-x 1 1001 1001  3648 531 2015 master_ip_failover
-rwxr-xr-x 1 1001 1001  9870 531 2015 master_ip_online_change
-rwxr-xr-x 1 1001 1001 11867 531 2015 power_manager
-rwxr-xr-x 1 1001 1001  1360 531 2015 send_report
# 脚本具体作用如下所示
# master_ip_failover:自动切换时 VIP 管理的脚本
# master_ip_online_change:在线切换时vip 的管理
# power_manager:故障发生后关闭主机的脚本
# send_report:因故障切换后发送报警的脚本

cp /root/mha4mysql-manager-0.57/samples/scripts/* /usr/local/bin
# 复制 “master_ip_failover” 脚本到/usr/local/bin 目录,
# 这里使用脚本管理 VIP,也是推荐的一种方式,生产环境不建议使用 Keepalived。

2、使用下面内容完整替换 master_ip_failover 文件的内容,IP 部分更换为自己的 IP地址

[root@manager ~]# cat /usr/local/bin/master_ip_failover
#!/usr/bin/env perl

#  Copyright (C) 2011 DeNA Co.,Ltd.
#  You should have received a copy of the GNU General Public License
#   along with this program; if not, write to the Free Software
#  Foundation, Inc.,
#  51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

## Note: This is a sample script and is not complete. Modify the script based on your environment.

use strict;
use warnings FATAL => 'all';

use Getopt::Long;
use MHA::DBHelper;

my (
  $command,        $ssh_user,         $orig_master_host,
  $orig_master_ip, $orig_master_port, $new_master_host,
  $new_master_ip,  $new_master_port,  $new_master_user,
  $new_master_password
);

my $vip = '192.168.72.200/24';
my $key = '1';
my $ssh_start_vip = "/sbin/ifconfig ens33:$key $vip up";
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,
  'new_master_user=s'     => \$new_master_user,
  'new_master_password=s' => \$new_master_password,
);

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";
}

3、创建 MHA 软件目录并拷贝配置文件

mkdir /etc/masterha
cp /root/mha4mysql-manager-0.57/samples/conf/app1.cnf /etc/masterha/
mkdir -p /var/log/masterha/app1

[root@manager ~]# cat /etc/masterha/app1.cnf
[server default]
manager_workdir=/var/log/masterha/app1
manager_log=/var/log/masterha/app1/manager.log
master_binlog_dir=/usr/local/mysql/data
master_ip_failover_script=/usr/local/bin/master_ip_failover
master_ip_online_change_script=/usr/local/bin/master_ip_online_change
user=mha
password=manager
ping_interval=1
remote_workdir=/tmp
repl_user=myslave
repl_password=123456
secondary_check_script=/usr/local/bin/masterha_secondary_check -s 192.168.72.132 -s 192.168.72.133
shutdown_script=""
ssh_user=root

[server1]
hostname=192.168.72.131
port=3306

[server2]
hostname=192.168.72.132
port=3306
candidate_master=1
check_repl_delay=0

[server3]
hostname=192.168.72.133
port=3306
  • candidate_master 与 check_repl_delay 的主要作用如下所示。
    • 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

4、添加用户添加软连接

# 在 master 节点
[root@master ~]# mysql -uroot -p123
grant all privileges on *.* to 'mha'@'192.168.72.%' identified by 'manager';
grant replication slave on *.* to 'myslave'@'192.168.72.%' identified by '123456';


# 三台数据库节点操作
ln -s /usr/local/mysql/bin/mysqlbinlog /usr/sbin/
ln -s /usr/local/mysql/bin/mysql /usr/sbin/

5、测试

# 测试 ssh 无密码认证,如果正常最后会输出 successfully
masterha_check_ssh -conf=/etc/masterha/app1.cnf
# 测试 mysq 主从连接情况,如果正常最后会输出 MySQL Replication Health is OK.
masterha_check_repl -conf=/etc/masterha/app1.cnf

6、首次配置 MHA 的 VIP 地址需要手动进行配置,在 master节点上执行如下命令

ifconfig ens33:1 192.168.72.200

7、启动 MHA

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

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 &


tail -f /var/log/masterha/app1/manager.log

8、master 节点关闭数据库

[root@master ~]# systemctl stop mysqld

9、slave1 节点查看是否自动切换

[root@slave1 ~]# ifconfig ens33:1

ens33:1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.72.200  netmask 255.255.255.0  broadcast 192.168.72.255
        ether 00:0c:29:d7:c5:02  txqueuelen 1000  (Ethernet)

六、模拟 master 故障

1、自动切换

# master 节点关闭数据库
[root@master ~]# systemctl stop mysqld

# 观察 MHA 日志,如果自动切换成功,最后会输出 successfully 字样
tail -f /var/log/masterha/app1/manager.log

# (1) 正常自动切换一次后,MHA 进程会退出。
# manager 会自动修改 app1.cnf 文件内容, 将宕机的 mysql 节点删除。查看 slave1 是否接管 VIP。
[root@slave1 ~]# ifconfig ens33:1

ens33:1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.72.200  netmask 255.255.255.0  broadcast 192.168.72.255
        ether 00:0c:29:d7:c5:02  txqueuelen 1000  (Ethernet)

  • 28
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值