mysql高可用之MHA

1.什么是 MHA

1.MHA Master High Availability )是一套优秀的 MySQL 高可用环境下故障切换和主从复制的软件。
2.MHA 的出现就是解决 MySQL 单点的问题。
3.MySQL 故障切换过程中, MHA 能做到 0-30 秒内自动完成故障切换操作。
4.MHA 能在故障切换的过程中最大程度上保证数据的一致性,以达到真正意义上的高可用。
1.为什么要用MHA
Master 的单点故障问题
2.MHA 的组成
1.MHA 由两部分组成 :MHAManager ( 管理节点 ) MHA Node ( 数据库节点 ), MHA Manager 可以单独部署在一台独立的机器上管理多个 master-slave 集群,也可以部署在一台 slave 节点上。
2.MHA Manager 会定时探测集群中的 master 节点。
3.当 master 出现故障时,它可以自动将最新数据的 slave 提升为新的 master , 然后将所有其他的
   slave 重新指向新的 master
3.MHA 的特点
1.自动故障切换过程中, MHA 从宕机的主服务器上保存二进制日志,最大程度的保证数据不丢失。
2.使用半同步复制,可以大大降低数据丢失的风险,如果只有一个 slave 已经收到了最新的二进制日志,MHA 可以将最新的二进制日志应用于其他所有的 slave 服务器上,因此可以保证所有节点的数据一致性。
3.目前 MHA 支持一主多从架构,最少三台服务,即一主两从。
4.故障切换备选主库的算法
1 .一般判断从库的是从( position/GTID )判断优劣,数据有差异,最接近于 master slave ,成为备选主机。
2 .数据一致的情况下,按照配置文件顺序,选择备选主库。
3 .设定有权重( candidate_master=1 ),按照权重强制指定备选主。
1 )默认情况下如果一个 slave 落后 master 100M relay logs 的话,即使有权重,也会失效。
2 )如果 check_repl_delay=0 的话,即使落后很多日志,也强制选择其为备选主
5.MHA工作原理
1.目前MHA主要支持一主多从的架构,要搭建MHA,要求一个复制集群必须最少有3台数据库服务器,一主二从,即一台充当Master,另一台台充当备用Master,另一台充当从库。
2.MHA Node 运行在每台 MySQL 服务器上。
3.MHAManager 会定时探测集群中的master 节点。
4.当master 出现故障时,它可以自动将最新数据的slave 提升为新的master。
5.然后将所有其他的slave 重新指向新的masterVIP自动漂移到新的master
6.整个故障转移过程对应用程序完全透明。

2.MHA部署实施

1.搭建一主两从架构
#在master节点中
[root@mysql1~]# /etc/init.d/mysqld stop

[root@mysql1 ~]# rm -fr /data/mysql/*

[root@mysql1 ~]# vim /etc/my.cnf

[mysqld]
datadir=/data/mysql
socket=/data/mysql/mysql.sock
server-id=1
log-bin=mysql-bin
gtid_mode=ON
log_slave_updates=ON
enforce-gtid-consistency=ON
symbolic-links=0

[root@mysql1 ~]# mysqld --user mysql --initialize
[root@mysql1 ~]# /etc/init.d/mysqld start
[root@mysql1 ~]# mysql_secure_installation
[root@mysql1 ~]# mysql -p

mysql> INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';

mysql> INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';

mysql> CREATE USER 'repl'@'%' IDENTIFIED BY '123123';
Query OK, 0 rows affected (0.00 sec)

mysql> GRANT REPLICATION SLAVE ON *.* TO repl@'%';
Query OK, 0 rows affected (0.00 sec)

mysql> INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';
Query OK, 0 rows affected (0.02 sec)

mysql> SET GLOBAL rpl_semi_sync_master_enabled = 1;
Query OK, 0 rows affected (0.00 sec)
#在slave1和slave2中
[root@mysql2 & 3 ~]# /etc/init.d/mysqld stop
[root@mysql2 & 3 ~]# rm -fr /data/mysql/*
[root@mysql2 & 3 ~]# vim /etc/my.cnf

[mysqld]
datadir=/data/mysql
socket=/data/mysql/mysql.sock
server-id=1
log-bin=mysql-bin
gtid_mode=ON
log_slave_updates=ON
enforce-gtid-consistency=ON
symbolic-links=0

[root@mysql2 & 3~]# mysqld --user mysql --initialize
[root@mysql2 & 3 ~]# /etc/init.d/mysqld start
[root@mysql2 & 3 ~]# mysql_secure_installation

[root@mysql2 & 3 ~]# mysql -p

mysql> INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';  #slave2不用输入,一 
                                                                          台备用主机就好
mysql> INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';    

mysql> CHANGE MASTER TO MASTER_HOST='172.25.254.10', MASTER_USER='repl',
MASTER_PASSWORD='123123', MASTER_AUTO_POSITION=1;
Query OK, 0 rows affected, 2 warnings (0.00 sec)

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

mysql> INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
Query OK, 0 rows affected (0.01 sec)

mysql> SET GLOBAL rpl_semi_sync_slave_enabled =1;
Query OK, 0 rows affected (0.00 sec)

mysql> STOP SLAVE IO_THREAD;
Query OK, 0 rows affected (0.00 sec)

mysql> START SLAVE IO_THREAD;
Query OK, 0 rows affected (0.00 sec)

mysql> SHOW STATUS LIKE 'Rpl_semi_sync%';
+----------------------------+-------+
| Variable_name | Value |
+----------------------------+-------+
| Rpl_semi_sync_slave_status | ON |
+----------------------------+-------+
1 row in set (0.01 sec)
2.安装MHA所需要的软件

 1.在软件中包含的工具包介绍 :

        1.masterha_check_ssh           #检查MHA SSH 配置状况
        2.masterha_check_repl           #检查MySQL 复制状况
        3.masterha_manger                 #启动MHA
        4.masterha_check_status        #检测当前MHA 运行状态
        5.masterha_master_monitor    #检测 master 是否宕机
        6.masterha_master_switch     #控制故障转移(自动或者手动)
        7.masterha_conf_host            #添加或删除配置的server 信息
2.Node工具包 (通常由masterHA主机直接调用,无需人为执行)
        1.save_binary_logs           #保存和复制 master 的二进制日志
        2.apply_diff_relay_logs      #识别差异的中继日志事件并将其差异的事件应用于其他的 slave
        3.filter_mysqlbinlog            #去除不必要的 ROLLBACK 事件( MHA 已不再使用这个工具)
        4.purge_relay_logs             #清除中继日志(不会阻塞 SQL 线程)
#在MHA中
[root@mysql-mha ~]# unzip MHA-7.zip

#下载所以安装包
[root@mysql-mha MHA-7]# yum install *.rpm -y 




#三台数据库均需要安装
[root@mysql-mha MHA-7]# scp mha4mysql-node-0.58-0.el7.centos.noarch.rpm
root@172.25.254.10:/mnt
[root@mysql-mha MHA-7]# scp mha4mysql-node-0.58-0.el7.centos.noarch.rpm
root@172.25.254.20:/mnt
[root@mysql-mha MHA-7]# scp mha4mysql-node-0.58-0.el7.centos.noarch.rpm
root@172.25.254.30:/mnt




#在sql-node中下载
[root@mysql 1~]# yum install /mnt/mha4mysql-node-0.58-
0.el7.centos.noarch.rpm -y
[root@mysql 2~]# yum install /mnt/mha4mysql-node-0.58-
0.el7.centos.noarch.rpm -y
[root@mysql 3~]# yum install /mnt/mha4mysql-node-0.58-
0.el7.centos.noarch.rpm -y

检验mysql半同步模式是否成功:

#在master中

[root@mysql1 ~]#mysql -uroot -p123123

mysql> show status like 'Rpl%';
+--------------------------------------------+-------+
| Variable_name                              | Value |
+--------------------------------------------+-------+
| Rpl_semi_sync_master_clients               | 2     |  #连接了两台slave
| Rpl_semi_sync_master_net_avg_wait_time     | 0     |
| Rpl_semi_sync_master_net_wait_time         | 0     |
| Rpl_semi_sync_master_net_waits             | 0     |
| Rpl_semi_sync_master_no_times              | 0     |
| Rpl_semi_sync_master_no_tx                 | 0     |
| Rpl_semi_sync_master_status                | ON    |  #master功能实现中
| Rpl_semi_sync_master_timefunc_failures     | 0     |
| Rpl_semi_sync_master_tx_avg_wait_time      | 0     |
| Rpl_semi_sync_master_tx_wait_time          | 0     |
| Rpl_semi_sync_master_tx_waits              | 0     |
| Rpl_semi_sync_master_wait_pos_backtraverse | 0     |
| Rpl_semi_sync_master_wait_sessions         | 0     |
| Rpl_semi_sync_master_yes_tx                | 0     |
| Rpl_semi_sync_slave_status                 | OFF   |  #slave功能关闭
+--------------------------------------------+-------+
#在slave中

[root@mysql2 ~]#mysql -uroot -p123123

mysql> show status like 'Rpl%';


+--------------------------------------------+-------+
| Variable_name                              | Value |
+--------------------------------------------+-------+
| Rpl_semi_sync_master_clients               | 0     |   #slave无机子相连
| Rpl_semi_sync_master_net_avg_wait_time     | 0     |
| Rpl_semi_sync_master_net_wait_time         | 0     |
| Rpl_semi_sync_master_net_waits             | 0     |
| Rpl_semi_sync_master_no_times              | 0     |
| Rpl_semi_sync_master_no_tx                 | 0     |
| Rpl_semi_sync_master_status                | ON    |   #master的候选备用机
| Rpl_semi_sync_master_timefunc_failures     | 0     |
| Rpl_semi_sync_master_tx_avg_wait_time      | 0     |
| Rpl_semi_sync_master_tx_wait_time          | 0     |
| Rpl_semi_sync_master_tx_waits              | 0     |
| Rpl_semi_sync_master_wait_pos_backtraverse | 0     |
| Rpl_semi_sync_master_wait_sessions         | 0     |
| Rpl_semi_sync_master_yes_tx                | 0     |
| Rpl_semi_sync_slave_status                 | ON    |   #slave服务启动中
+--------------------------------------------+-------+

3.配置MHA 的管理环境

1.生成配置目录和配置文件
#因为我们当前只有一套主从,所以我们只需要写一个配置文件即可

[root@mysql-mha ~]# masterha_manager --help
Usage:
masterha_manager --global_conf=/etc/masterha_default.cnf #全局配置文件,记录公共设定

--conf=/usr/local/masterha/conf/app1.cnf                 #不同管理配置文件,记录各自配置



See online reference
(http://code.google.com/p/mysql-master-ha/wiki/masterha_manager) for
details.
2.解压源码包后在samples中找到配置文件的模板文件:
#生成配置文件
[root@mysql-mha ~]# mkdir /etc/masterha
[root@mysql-mha MHA-7]# tar zxf mha4mysql-manager-0.58.tar.gz
[root@mysql-mha MHA-7]# cd mha4mysql-manager-0.58/samples/conf/
[root@mysql-mha conf]# cat masterha_default.cnf app1.cnf >
/etc/masterha/app1.cnf

3.配置相关的文件:

#编辑配置文件

[root@mysql-mha ~]# vim /etc/masterha/app1.cnf
[server default]
user=root                             #mysql管理员用户,因为需要做自动化配置

password=123123                          #mysql密码

ssh_user=root                         #ssh远程登陆用户

repl_user=repl                        #mysql主从复制中负责认证的用户

repl_password=123123                  #mysql主从复制中负责认证的用户密码

master_binlog_dir= /data/mysql        #二进制日志目录

remote_workdir=/tmp                   #远程工作目录

#此参数使为了提供冗余检测,方式是mha主机网络自身的问题无法连接数据库节点,应为集群之外的主机
# 检查从服务器状态的脚本   其中 172.25.254.10 为MASTER 的IP地址  
# 172.25.254.11 为备用地址 假如说找不到172.25.254.10 就找172.25.254.11
secondary_check_script= masterha_secondary_check -s 172.25.254.10 -s
172.25.254.11

ping_interval=3                       #每隔3秒检测一次

#发生故障后调用的脚本,用来迁移vip
# master_ip_failover_script= /script/masterha/master_ip_failover

# shutdown_script= /script/masterha/power_manager      #电源管理脚本

#当发生故障后用此脚本发邮件或者告警通知
# report_script= /script/masterha/send_report

#在线切换时调用的vip迁移脚本,手动
# master_ip_online_change_script= /script/masterha/master_ip_online_change

manager_workdir=/etc/masterha                         #mha工作目录
manager_log=/var/etc/masterha/manager.log             #mha日志



[server1]
hostname=172.25.254.10
candidate_master=1                 #可能作为master的主机

check_repl_delay=0                 ##默认情况下如果一个slave落后master 100M的relay logs的话
                                    #MHA将不会选择该slave作为一个新的master,
                                    #因为对于这个slave的恢复需要花费很长时间,
                                    #通过设置check_repl_delay=0,
                                    #MHA触发切换在选择一个新的master的时候将会忽略复制延时,
                                    #这个参数对于设置了candidate_master=1的主机非常有用,
                                    #因为这个候选主在切换的过程中一定是新的master。



[server2]
# 主机名
hostname=172.25.254.20


# 是否候选主服务器
candidate_master=1


# 检查复制延迟(秒
check_repl_delay=0

 
[server3]
# 主机名
hostname=172.25.254.30

# 不为主服务器
no_master=1

1.检测配置

1. 检测网络及ssh免密

[root@mysql-mha ~]# masterha_check_ssh --conf=/etc/masterha/app1.cnf

.。。。。。省略

Warning: Permanently added '172.25.254.20' (ECDSA) to the list of known hosts.
Fri Aug 2 16:57:42 2024 - [debug] ok.
Fri Aug 2 16:57:43 2024 - [info] All SSH connection tests passed successfully.

2.检测数据主从复制情况

#在数据节点master端

mysql> GRANT ALL ON *.* TO root@'%' identified by '123123';     #允许root远程登陆



#执行检测,在mha端

[root@mysql-mha ~]# masterha_check_repl --conf=/etc/masterha/app1.cnf

。。。。。。省略

Fri Aug 2 17:04:21 2024 - [warning] shutdown_script is not defined.
Fri Aug 2 17:04:21 2024 - [info] Got exit code 0 (Not master dead).
MySQL Replication Health is OK.

如上所述,出现的结果则环境部署ok,没有问题。

4.MHA的故障切换

MHA的故障切换过程:
共包括以下的步骤:
1. 配置文件检查阶段,这个阶段会检查整个集群配置文件配置
2. 宕机的 master 处理,这个阶段包括虚拟 ip 摘除操作,主机关机操作
3. 复制 dead master 和最新 slave 相差的 relay log ,并保存到 MHA Manger 具体的目录下
4. 识别含有最新更新的 slave
5. 应用从 master 保存的二进制日志事件( binlog events
6. 提升一个 slave 为新的 master 进行复制
7. 使其他的 slave 连接新的 master 进行复制
1.切换方式:
1.master未出现故障手动切换
#在master数据节点还在正常工作情况下

[root@mysql-mha ~]# masterha_master_switch \
--conf=/etc/masterha/app1.cnf \                 #指定配置文件
--master_state=alive \                          #指定master节点状态
--new_master_host=172.25.254.20 \               #指定新master节点
--new_master_port=3306 \                        #执行新master节点端口
--orig_master_is_new_slave \                    #原始master会变成新的slave
--running_updates_limit=10000                   #切换的超时时间

切换:

#切换过程如下:
[root@mysql-mha masterha]# masterha_master_switch --conf=/etc/masterha/app1.cnf -
-master_state=alive --new_master_host=172.25.254.20 --new_master_port=3306 --
orig_master_is_new_slave --running_updates_limit=10000

Fri Aug 2 18:30:38 2024 - [info] MHA::MasterRotate version 0.58.
Fri Aug 2 18:30:38 2024 - [info] Starting online master switch..
Fri Aug 2 18:30:38 2024 - [info]
Fri Aug 2 18:30:38 2024 - [info] * Phase 1: Configuration Check Phase..
.......省略
Fri Aug 2 18:30:46 2024 - [info]
Fri Aug 2 18:30:46 2024 - [info] 172.25.254.20: Resetting slave info succeeded.
Fri Aug 2 18:30:46 2024 - [info] Switching master to
172.25.254.20(172.25.254.20:3306) completed successfully.

最后结束段为172.25.254.20(172.25.254.20:3306) completed successfully,则成功切换。

2.master故障手动切换
#模拟master故障
[root@mysql-node20 mysql]# /etc/init.d/mysqld stop

故障输入参数:
--master_state              #主服务器的状态,这里为 dead 表示主服务器已死机
--conf                            #指定 MHA 配置文件的位置,例如:/etc/masterha/app1.cnf
--dead_master_host     #死机的主服务器的 IP 地址,例如:192.168.239.10
--dead_master_port     #死机的主服务器的端口,例如:3306
--new_master_host      #新的主服务器的 IP 地址,例如:192.168.239.20
--new_master_port      #新的主服务器的端口,例如:3306
--ignore_last_failover   #忽略最近一次的故障转移记录(忽略锁表)

#在MHA中做故障切换
[root@mysql-mha masterha]# masterha_master_switch --master_state=dead --
conf=/etc/masterha/app1.cnf --dead_master_host=192.168.56.10 --
dead_master_port=3306 --new_master_host=192.168.56.20 --new_master_port=3306 --
ignore_last_failover


--ignore_last_failover 表示忽略在/etc/masterha/目录中在切换过程中生成的锁文件

切换过程:

[root@mysql-mha masterha]#masterha_master_switch --master_state=dead --conf=/etc/masterha/app1.cnf --dead_master_host=172.25.254.20 --dead_master_port=3306 --
new_master_host=172.25.254.10 --new_master_port=3306 --ignore_last_failover


--dead_master_ip=<dead_master_ip> is not set. Using 172.25.254.10.
Fri Aug 2 19:38:35 2024 - [warning] Global configuration file
/etc/masterha_default.cnf not found. Skipping.
Fri Aug 2 19:38:35 2024 - [info] Reading application default configuration from
/etc/masterha/app1.cnf..
Fri Aug 2 19:38:35 2024 - [info] Reading server configuration from
/etc/masterha/app1.cnf..
Fri Aug 2 19:38:35 2024 - [info] MHA::MasterFailover version 0.58
.........省略
Starting master switch from 172.25.254.20(172.25.254.20:3306) to
172.25.254.10(172.25.254.10:3306)? (yes/NO): yes

Fri Aug 2 19:38:41 2024 - [info] New master decided manually is 172.25.254.10(172.25.254.10:3306)

........省略
172.25.254.10(172.25.254.10:3306): OK: Applying all logs succeeded.
172.25.254.30(172.25.254.30:3306): OK: Slave started, replicating from
172.25.254.10(172.25.254.10:3306)
172.25.254.10(172.25.254.10:3306): Resetting slave info succeeded.
Master failover to 172.25.254.20(172.25.254.10:3306) completed successfully.

最后出现Master failover to 172.25.254.20(172.25.254.10:3306) completed successfully.则成功切换。

恢复故障mysql节点:
在故障的node1上,将node1设置为172.25.254.20的slave机,20为10的master。
[root@mysql1 ~]# /etc/init.d/mysqld start
Starting MySQL. SUCCESS!
[root@mysql1 tmp]# mysql -p
mysql> CHANGE MASTER TO MASTER_HOST='172.25.254.20', MASTER_USER='repl',
MASTER_PASSWORD='123123', MASTER_AUTO_POSITION=1;
mysql> show slave\G;
#测试一主两从是否正常

[root@mysql-mha masterha]# masterha_check_repl --conf=/etc/masterha/app1.cnf
Fri Aug 2 20:15:29 2024 - [info] Checking replication health on 172.25.254.20..
Fri Aug 2 20:15:29 2024 - [info] ok.
Fri Aug 2 20:15:29 2024 - [info] Checking replication health on 172.25.254.30..
Fri Aug 2 20:15:29 2024 - [info] ok.
Fri Aug 2 20:15:29 2024 - [warning] master_ip_failover_script is not defined.
Fri Aug 2 20:15:29 2024 - [warning] shutdown_script is not defined.
Fri Aug 2 20:15:29 2024 - [info] Got exit code 0 (Not master dead).
MySQL Replication Health is OK.

3.自动切换

设置master恢复为10,20和30为从机slave。

[root@docker-rhel masterha]# masterha_master_switch \
--conf=/etc/masterha/app1.cnf \
--master_state=alive \
--new_master_host=172.25.254.10 \
--new_master_port=3306 \
--orig_master_is_new_slave \
--running_updates_limit=10000

[root@mysql-mha masterha]# rm -fr app1.failover.complete #删掉切换锁文件

#监控程序通过指定配置文件监控master状态,当master出问题后自动切换并退出避免重复做故障切换
[root@mysql-mha masterha]# masterha_manager --conf=/etc/masterha/app1.cnf

#查看运行日志
[root@mysql-mha masterha]# cat /etc/masterha/manager.log

重启后需要手动恢复故障mysql节点:
在故障的node1上,将node1设置为172.25.254.20的slave机,20为10的master。
[root@mysql1 ~]# /etc/init.d/mysqld start
Starting MySQL. SUCCESS!
[root@mysql1 tmp]# mysql -p
mysql> CHANGE MASTER TO MASTER_HOST='172.25.254.20', MASTER_USER='repl',
MASTER_PASSWORD='123123', MASTER_AUTO_POSITION=1;
mysql> show slave\G;

5.MHA添加VIP功能

使用脚本实现VIP漂移功能

[root@mysql-mha ~]# cp master_ip_failover master_ip_online_change
/usr/local/bin/
[root@mysql-mha ~]# chmod +x /usr/local/bin/master_ip_*

自动切换脚本:

完整代码:

#!/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.239.100/24';
my $ssh_start_vip = "/sbin/ip addr add $vip dev eth0";
my $ssh_stop_vip = "/sbin/ip addr del $vip dev eth0";
 
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";
}

手动切换脚本

#!/usr/bin/env perl
use strict;  
use warnings FATAL =>'all';  
  
use Getopt::Long;  
  
my $vip = '192.168.239.100/24';
my $ssh_start_vip = "/sbin/ip addr add $vip dev eth0";  
my $ssh_stop_vip = "/sbin/ip addr del $vip dev eth0";  
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  
"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";  
}

在配置文件中修改启动的路径:vim /etc/masterha/app1.cnf,保存退出。

[root@mysql-mha masterha]# masterha_manager --conf=/etc/masterha/app1.cnf & 启动监
控程序
[root@mysql-node10 tmp]# ip a a 172.25.254.100/24 dev eth0 #在master节点添加VIP
模拟故障:
VIP172.25.254.100在10master端上。
 
[root@mysql1 ~]# /etc/init.d/mysqld stop #关闭主节点服务
[root@mysql-mha masterha]# cat manager.log

查看日志发现vip172.25.254.100飘逸到新的master端20上去了。

恢复故障主机
重启后需要手动恢复故障mysql节点:
在故障的node1上,将node1设置为172.25.254.20的slave机,20为10的master。
[root@mysql1 ~]# /etc/init.d/mysqld start
Starting MySQL. SUCCESS!
[root@mysql1 tmp]# mysql -p
mysql> CHANGE MASTER TO MASTER_HOST='172.25.254.20', MASTER_USER='repl',
MASTER_PASSWORD='123123', MASTER_AUTO_POSITION=1;
mysql> show slave\G;

手动切换后查看 vip 变化
手动切换前得删除掉锁文件,不然无法运行
[root@mysql masterha]# rm -rf app1.failover.complete
[root@mysql-mha masterha]# masterha_master_switch --conf=/etc/masterha/app1.cnf
--master_state=alive --new_master_host=172.25.254.20 --new_master_port=3306 --
orig_master_is_new_slave --running_updates_limit=10000

手动输入切换后查看vip:

[root@mysq2 ~]# 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
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP
group default qlen 1000
link/ether 00:0c:29:cb:63:ce brd ff:ff:ff:ff:ff:ff
inet 172.25.254.20/24 brd 172.25.254.255 scope global noprefixroute eth0
valid_lft forever preferred_lft forever
inet 172.25.254.100/24 scope global secondary eth0
valid_lft forever preferred_lft forever

已经漂移过来了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值