一、MHA介绍
1.1 MHA概述
- 一套优秀的作为MySQL高可用性环境下故障切换和主从提升的高可用软件
- 支持故障切换
- 在MySQL故障切换过程中,MHA能做到在0~30秒之内自动完成数据库的故障切换操作,并且在进行故障切换的过程中,MHA能在最大程度上保证数据的一致性,以达到真正意义上的高可用
1.2 MHA组成
- MHA Manager(管理节点)
- MHA Node(数据节点)
1.3 MHA的特点
- 自动故障切换过程中,MHA试图从宕机的主服务器上保存二进制日志,最大程度的保证数据的不丢失
- 使用 MySQL55的半同步复制,可以大大降低数据丢失的风险
- 目前MHA支持一主多从架构,最少三台服务,即一主两从
二、MHA实验
实验目的
- 通过MHA监控MySQL数据库,在故障时自动进行切换,不影响业务
- 当主库失效时,备选主库自动成为主库
实验拓扑图
.实验思路
1) 安装 MySQL 数据库
2) 配置 MySQL 一主两从
3) 安装 MHA 软件
4) 配置无密码认证
5) 配置 MySQL MHA 高可用
6) 模拟 master 故障切换
.1 安装mysql
在三台 MySQL 节点上分别安装数据库,MySQL 版本请使用 ,cmake 版本请使
用 。之前博客有详细安装mysql步骤,这边不再说明。
.2 搭建mysql主从复制环境
- 所有数据库授权mha用户对数据库的操作权限,每一个mysql数据库都要设置
1在所有数据库节点上授权两个用户,一个是从库同步使用,另外一个是 manager 使用。
2 mysql> grant replication slave on *.* to 'myslave'@'1968.195.%' identified by '123';
3 mysql> grant all privileges on *.* to 'mha'@'1968.195.%' identified by 'manager';
4 mysql> flush privileges;
.3 在 Mysql1 主机上查看二进制文件和同步点
mysql> show master status;
+-------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+-------------------+----------+--------------+------------------+-------------------+
| master-bin.000001 | 1215 | | | |
+-------------------+----------+--------------+------------------+-------------------+
.4 接下来在 Mysql2 和 Mysql3 分别执行同步。
mysql> change master to master_host='1968.195.129',master_user='myslave',master_password='123',master_log_file='',master_log_pos=1215;
mysql> start slave;
.5 查看 IO 和 SQL 线程都是 yes 代表同步是否正常。
mysql> show slave status\G;
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
必须设置两个从库为只读模式:
mysql> setglobal read_only=1;
所有节点安装环境和Node组件和Manager组件
- 所有服务器上都要安装mha依赖的环境,此处仅展示mha_manager的安装
[root@mha_manager ~]# yum install epel-release --nogpgcheck -y
[root@mha_manager ~]# yum install -y perl-DBD-MySQL \
perl-Config-Tiny \
perl-Log-Dispatch \
perl-Parallel-ForkManager \
perl-ExtUtils-CBuilder \
perl-ExtUtils-MakeMaker \
perl-CPAN
- 所有服务器都安装安装node组件,此处仅展示master服务器的安装
[root@master ~]# tar zxvf /mnt/shuju数据库/mha/mha4mysql-node-0.57.tar.gz
[root@master ~]# cd mha4mysql-node-0.57/
[root@master mha4mysql-node-0.57]# yum install perl-Module-Install -y
[root@master mha4mysql-node-0.57]# perl Makefile.PL
==> Auto-install the 1 mandatory module(s) from CPAN? [y] y '//输入y'
[root@master mha4mysql-node-0.57]# make
[root@master mha4mysql-node-0.57]# make install
- 仅mha_manager服务器安装manager组件
[root@mha_manager ~]# tar zxvf /mnt/shuju数据库/mha/mha4mysql-manager-0.57.tar.gz
[root@mha_manager ~]# cd mha4mysql-manager-0.57/
[root@mha_manager mha4mysql-manager-0.57]# perl Makefile.PL
[root@mha_manager mha4mysql-manager-0.57]# make
[root@mha_manager mha4mysql-manager-0.57]# make install
2.5 配置节点间SSH免交互登陆
- mha_manager主机配置到所有数据库节点的密钥对验证
[root@MHA-manager ~]# ssh-keygen -t rsa //一路按回车键
[root@MHA-manager ~]# ssh-copy-id 1968.195.129
[root@MHA-manager ~]# ssh-copy-id 1968.195.130
[root@MHA-manager ~]# ssh-copy-id 1968.195.131
- 在master上配置到数据库节点slave1和slave2的免密验证
[root@Mysql1 ~]# ssh-keygen -t rsa
[root@Mysql1 ~]# ssh-copy-id 1968.195.130
[root@Mysql1 ~]# ssh-copy-id 1968.195.131
- 在slave1上配置到数据库节点master和slave2的免密验证
[root@Mysql2 ~]# ssh-keygen -t rsa
[root@Mysql2 ~]# ssh-copy-id 1968.195.129
[root@Mysql2 ~]# ssh-copy-id 1968.195.131
- 在slave2上配置到数据库节点master和slave1的免密验证
[root@Mysql3 ~]# ssh-keygen -t rsa
[root@Mysql3 ~]# ssh-copy-id 1968.195.129
[root@Mysql3 ~]# ssh-copy-id 1968.195.130
2.6 配置MHA-Manager组件
- 在 manager 节点上复制相关脚本到/usr/local/bin 目录
[root@mha_manager ~]# cp -ra /root/mha4mysql-manager-0.57/samples/scripts /usr/local/bin
[root@mha_manager samples]# ls -l /usr/local/bin/scripts/
-rwxr-xr-x. 1100110013648 5月 312015 master_ip_failover 自动切换时 VIP管理的脚本
-rwxr-xr-x. 1100110019870 5月 312015 master_ip_online_change 在线切换VIP的管理
-rwxr-xr-x. 11001100111867 5月 312015 power_manager 故障发生后关闭主机的脚本
-rwxr-xr-x. 1100110011360 5月 312015 send_report 因故障切换后发送报警的脚本
[root@mha_manager ~]# cp /usr/local/bin/scripts/master_ip_failover /usr/local/bin/ '//自动切换时 VIP管理的脚本'
[root@mha_manager ~]# vim /usr/local/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 = '1968.195.200';
my $brdc = '1968.195.255';
my $ifdev = 'ens33';
my $key = '1';
my $ssh_start_vip = "/sbin/ifconfig ens33:$key $vip";
my $ssh_stop_vip = "/sbin/ifconfig ens33:$key down";
my $exit_code = 0;
#my $ssh_start_vip = "/usr/sbin/ip addr add $vip/24 brd $brdc dev $ifdev label $ifdev:$key;/usr/sbin/arping -q -A -c 1 -I $ifdev $vip;iptables -F;";
#my $ssh_stop_vip = "/usr/sbin/ip addr del $vip/24 dev $ifdev label $ifdev:$key";
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";
}
[root@MHA-manager ~]# mkdir /etc/masterha
[root@MHA-manager ~]# cp /root/mha4mysql-manager-0.57/samples/conf/ /etc/masterha/
[root@MHA-manager ~]# vim /etc/masterha/
[server default]
manager_workdir=/var/log/masterha/app1.log ##manager工作目录
manager_log=/var/log/masterha/app1/manager.log #manager日志
master_binlog_dir=/usr/local/mysql/data/ #master保存binlog的位置,这里的路径要与master里配置的binlog的路径一致,以便mha能找到
#master_ip_failover_script= /usr/local/bin/master_ip_failover #设置自动failover时候的切换脚本,也就是上边的哪个脚本
master_ip_online_change_script= /usr/local/bin/master_ip_online_change #设置手动切换时候的切换脚本
password=manager #设置mysql中root用户的密码,这个密码是前文中创建监控用户的那个密码
user=mha #设置监控用户root
ping_interval=1 #设置监控主库,发送ping包的时间间隔,默认是3秒,尝试三次没有回应的时候自动进行railover
remote_workdir=/tmp #设置远端mysql在发生切换时binlog的保存位置
repl_password=123 #设置复制用户的密码
repl_user=myslave #设置复制用户的用户
report_script=/usr/local/send_report //设置发生切换后发送的报警的脚本
secondary_check_script=/usr/local/bin/masterha_secondary_check -s 1968.195.130 -s 1968.195.131
shutdown_script="" #设置故障发生后关闭故障主机脚本(该脚本的主要作用是关闭主机放在发生脑裂,这里没有使用)
ssh_user=root #设置ssh的登录用户名
[server1]
hostname=1968.195.129
port=3306
[server2]
hostname=1968.195.130
port=3306
candidate_master=1 #//设置为候选master,如果设置该参数以后,发生主从切换以后将会将此从库提升为主库,即使这个主库不是集群中事件最新的slave
check_repl_delay=0
[server3] hostname=1968.195.131 port=3306
2.7 测试 ssh 无密码认证,如果正常最后会输出 successfully,如下所示
[root@MHA-manager ~]# masterha_check_ssh -conf=/etc/masterha/
Tue Nov 2623:09:452019 - [warning] Global configuration file /etc/masterha_default.cnf not found. Skipping.
Tue Nov 2623:09:452019 - [info] Reading application default configuration from /etc/masterha/..
Tue Nov 2623:09:452019 - [info] Reading server configuration from /etc/masterha/..
Tue Nov 2623:09:452019 - [info] Starting SSH connection tests..
Tue Nov 2623:09:462019 - [debug]
Tue Nov 2623:09:452019 - [debug] Connecting via SSH from root@1968.195.130(1968.195.130:22) to root@1968.195.131(1968.195.131:22)..
Tue Nov 2623:09:462019 - [debug] ok.
Tue Nov 2623:09:472019 - [debug]
Tue Nov 2623:09:462019 - [debug] Connecting via SSH from root@1968.195.131(1968.195.131:22) to root@1968.195.130(1968.195.130:22)..
Tue Nov 2623:09:472019 - [debug] ok.
Tue Nov 2623:09:472019 - [info] All SSH connection tests passed successfully.
2.8 启动MHA
[root@Mysql1 ~]# /sbin/ifconfig ens33:11968.195.200/24
[root@MHA-manager ~]# nohup masterha_manager --conf=/etc/masterha/ --remove_dead_master_conf --ignore_last_failover < /dev/null > /var/log/masterha/app1/manager.log 2>&1 &
[1] 129929
三、验证实验
1 [root@MHA-manager ~]#tailf /var/log/masterha/app1/manager.log //启用监控观察日志记录2 [root@Mysql1 ~]# pkill -9 mysql //查看master变化
故障模拟:
可以看到从库的状态,其中之一肯定有切换到主库的
切换备选主库的算法:
1.一般判断从库的是从(position/GTID)判断优劣,数据有差异,最接近于master的slave,成为备选主。
2.数据一致的情况下,按照配置文件顺序,选择备选主库。
3.设定有权重(candidate_master=1),按照权重强制指定备选主。
1)默认情况下如果一个slave落后master 100M的relay logs的话,即使有权重,也会失效。
2)如果check_repl_delay=0的话,即使落后很多日志,也强制选择其为备选主。
故障修复步骤:
>change master to master_host='1968.195.130',master_user='myslave',master_password='123',master_log_file='',master_log_pos=154;
>start slave;
- 修改配置文件(再把这个记录添加进去,因为它检测掉失效时候会自动消失)
vi /etc/masterha/
[server1]
hostname=1968.195.129
port=3306
nohup masterha_manager --conf=/etc/masterha/ --remove_dead_master_conf --ignore_last_failover < /dev/null > /var/log/masterha/app1/manager.log 2>&1 &