MHA(Master High Availability)是由日本一家公司开发的一套 MySQL 高可用性环境下故障切换和主从提升的高可用软件,目前在 MySQL 高可用方面是一个相对成熟的的解决方案。在 MySQL 故障切换过程中,MHA 能做到在 0~30 秒之内自动完成数据库的故障切换操作,并且在进行故障切换的过程中,MHA 能在最大程度上保证数据的一致性,以达到真正意义上的高可用。
MHA 由 Manager 节点和 Node 节点组成;MHA Manager 可以单独部署在一台独立的机器上管理多个 master-slave 集群,也可以部署在一台 slave 节点上。MHA Node 运行在每台 MySQL 服务器上。
准备工作:
主机名 | 操作系统 | IP地址 | 担任角色 |
master | CentOS7 | 192.168.1.1 | MySQL-主节点 |
slave1 | 192.168.1.2 | MySQL-从节点 | |
slave2 | 192.168.1.3 | MySQL-从节点 | |
manager | 192.168.1.4 | MHA manager 节点 |
由于 MHA manager 通过 SSH 访问所有的 node 节点,各个 node 节点也同样通过 SSH 来相互发送不同的 relay log 文件,所以要在每一个 node 和 manager 上配置 SSH 无密码登陆。
[root@master ~]# ssh-keygen -t rsa #一路回车即可
[root@master ~]# ssh-copy-id 192.168.1.2
[root@master ~]# ssh-copy-id 192.168.1.3
[root@master ~]# ssh-copy-id 192.168.1.4
准备工作:四台机器都要做
[root@manager ~]# mkdir /root/mha
[root@manager ~]# cd /root/mha
[root@manager mha]# ls
mha4mysql-manager-0.57-0.el7.noarch.rpm mhapath.tar.gz mha4mysql-node-0.57-0.el7.noarch.rpm
[root@manager mha]# tar zxf mhapath.tar.gz
[root@manager mha]# cat <<END > /etc/yum.repos.d/CentOS7.repo
[centos]
name=centos7
baseurl=file:///mnt
enabled=1
gpgcheck=0
[mha]
name=mha
baseurl=file:///root/mha/mhapath
enabled=1
gpgcheck=0
END
[root@manager mha]# mount /dev/cdrom /mnt/
[root@manager ~]# yum -y install perl-DBD-MySQL perl-Config-Tiny perl-Log-Dispatch perl-Parallel-ForkManager --skip-broken --nogpgcheck
[root@manager ~]# rpm -ivh /root/mha/mha4mysql-node-0.57-0.el7.noarch.rpm
[root@manager ~]# yum -y install perl-DBD-MySQL perl-Config-Tiny perl-Log-Dispatch perl-Parallel-ForkManager perl-Time-HiRes perl-ExtUtils-CBuilder perl-ExtUtils-MakeMaker perl-CPAN
[root@manager ~]# rpm -ivh /root/mha/mha4mysql-manager-0.57-0.el7.noarch.rpm
在 manager 节点安装完成后会生成一些管理工具,manager 的主要管理工具有:
masterha_check_ssh
:检查 MHA 的 SSH 配置状况。masterha_check_repl
:检查 MySQL 复制状况。masterha_manager
:启动 MHA。masterha_check_status
:检查当前 MHA 运行状态。masterha_master_monitor
:检查 Master 是否宕机。masterha_master_switch
:控制故障转移(自动或者手动)。masterha_conf_host
:添加或删除配置的 server 信息。[root@master ~]# cat <<END >> /etc/my.cnf
log-bin=mysql-bin-master
server-id=1
END
[root@master ~]# systemctl restart mysqld
[root@master ~]# mysql -uroot -p123456
mysql> grant replication slave on *.* to repl@'192.168.1.%' identified by '123456';
mysql> grant all privileges on *.* to root@'192.168.1.%' identified by '123456';
mysql> flush privileges;
mysql> exit
[root@slave1 ~]# cat <<END >> /etc/my.cnf
log-bin=mysql-slave1 #slave2改为2
server-id=2 #slave2改为3
log_slave_updates=1
END
[root@slave1 ~]# systemctl restart mysqld
[root@slave1 ~]# mysql -uroot -p123456
mysql> grant replication slave on *.* to repl@'192.168.1.%' identified by '123456';
mysql> grant all privileges on *.* to root@'192.168.1.%' identified by '123456';
mysql> flush privileges;
mysql> exit
两台从节点操作一致
[root@slave1 ~]# mysql -uroot -p123456
mysql> change master to
master_host='192.168.1.1',
master_user='repl',
master_password='123456';
mysql> start slave;
mysql> show slave status\G;
[root@master ~]# ln -s /usr/local/mysql/bin/mysql /usr/bin/mysql
[root@master ~]# ln -s /usr/local/mysql/bin/mysqlbinlog /usr/local/bin/mysqlbinlog
[root@slave1 ~]# mysql -uroot -p123456 -e 'set global read_only=1'
[root@slave1 ~]# mysql -uroot -p123456 -e 'set global relay_log_purge=0'
[root@manager ~]# mkdir -p /etc/masterha
[root@manager ~]# mkdir -p /var/log/masterha/app1
[root@manager ~]# vim /etc/masterha/app1.cnf
[server default]
manager_workdir=/var/log/masterha/app1 #设置 manager 的工作目录
manager_log=/var/log/masterha/app1/manager.log #设置 manager 的日志文件
master_binlog_dir=/usr/local/mysql/data/ #设置 master 保存 binlog 的位置,以便 MHA 可以找到 master 的日志
user=root #设置监控 mysql 的用户
password=123456 #设置监控 mysql 用户的密码
ping_interval=1 #设置监控主库,发送 ping 包的时间间隔
remote_workdir=/tmp #设置远端 mysql 在发生切换时 binlog 的保存位置
repl_user=repl #设置 mysql 中用于复制的用户
repl_password=123456 #设置 mysql 中用于复制的用户密码
ssh_user=root #设置 ssh 的登录用户名
[server1]
hostname=192.168.1.1
port=3306
[server2]
hostname=192.168.1.2
port=3306
candidate_master=1 #设置当前节点为候选的 master
check_repl_delay=0 #当落后 master 100M 的 relay logs 时,MHA 将不会选择该 slave 作为一个新的 master
[server3]
hostname=192.168.1.3
port=3306
[root@manager ~]# masterha_check_ssh --conf=/etc/masterha/app1.cnf
[root@manager ~]# masterha_check_repl --conf=/etc/masterha/app1.cnf
MySQL 中主从的工作状态检测及切换是由 manager 节点来完成的,MHA 安装完成以及检测通过后就可以根据自己的需求开启以及停止 manager。
Manager 是通过 masterha_manager
命令开启,启动后需要将它放在后台运行。
[root@manager ~]# 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 &
当 MHA manager 启动监控以后,如果没有异常则不会打印任何信息。我们可通过 masterha_check_status
命令检查 manager 的状态。
[root@manager ~]# masterha_check_status --conf=/etc/masterha/app1.cnf
通过 MHA 进行故障转以后,连接 MySQL 数据库的服务并不知道 MySQL 复制环境中进行了故障的转移,同时连 MySQL 的服务也无法知晓主节点是哪一个,此时,可以通过配置 VIP 的方式让所有的应用程序连接 VIP,当 MySQL 故障切换时,VIP 会自动漂移到新的主节点。
[root@master ~]# ifconfig ens33:1 192.168.1.188 netmask 255.255.255.0 up
[root@master ~]# ifconfig ens33:1
[root@manager ~]# vim /etc/masterha/app1.cnf
在 [server default] 项下面添加:
master_ip_failover_script=/usr/bin/master_ip_failover
[root@master ~]# vim /usr/bin/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.1.188/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 \"`;
}
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";
}
[root@manager ~]# chmod +x /usr/bin/master_ip_failover #添加可执行权限
再次检测,结果应该和上面检测结果一样才对
[root@manager ~]# masterha_check_repl --conf=/etc/masterha/app1.cnf
[root@manager ~]# 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 &
[root@manager ~]# masterha_check_status --conf=/etc/masterha/app1.cnf
[root@master ~]# systemctl stop mysqld
[root@manager ~]# tail -n10 /var/log/masterha/app1/manager.log
[root@slave1 ~]# ifconfig ens33:1