主机如下:
192.168.209.131---主
192.168.209.132---从 (可切换为主)
192.168.209.128---从(不可以切换为主) 和 mha管理服务器
1.在三台数据库服务器安装好mysql,三台数据库开启gtid,都开启了bin-log和log_slave_updates = 1 实现主从同步
2.三台服务器之间需要实现无需密码ssh登陆
(三台服务器都要执行下面四条命令)
ssh-keygen #生产私钥
ssh-copy-id -i /root/.ssh/id_rsa '-p 22 root@192.168.209.128'
ssh-copy-id -i /root/.ssh/id_rsa '-p 22 root@192.168.209.131'
ssh-copy-id -i /root/.ssh/id_rsa '-p 22 root@192.168.209.132'
3.三台服务器安装epel源
wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-6.repo
4.安装依赖组件和安装mha客户端
(三台服务器都要)
yum -y install perl-DBD-MySQL ncftp perl-DBI
rpm -ivh mha4mysql-node-0.56-0.el6.noarch.rpm
5.在mha管理服务器安装相关依赖组件和mha管理端
192.168.209.128
yum install -y perl-Config-Tiny epel-release perl-Log-Dispatch perl-Parallel-ForkManager perl-Time-HiRes
rpm -ivh mha4mysql-manager-0.56-0.el6.noarch.rpm
mkdir -p /etc/mha #配置目录,存储mha配置文件
mkdir -p /home/mysql_mha #工作目录,存储mha日志文件和其他文件
6.在非mha管理服务器,创建工作目录
mkdir -p /home/mysql_mha
7.在master数据库创建mha管理用户
#在主服务器上执行,然后同步到其他slave服务器,mha用户管理主从
grant all privileges on *.* to mha@'192.168.209.%' identified by '123456';
8.在mha服务器创建配置文件
cd /etc/mha
vim mysql_mha.cnf
----------------------
[server default]
#mha管理端日志目录
manager_log=/home/mysql_mha/manager.log
#mha管理端工作目录
manager_workdir=/home/mysql_mha
#主数据库binlog存储目录(建议所有数据库的bin-log目录一致)
master_binlog_dir=/data/mysql/datanode1
#其他从服务器的工作目录,需要在其他从服务器手动创建这个目录
remote_workdir=/home/mysql_mha
#mha为管理主从的管理用户
user=mha
password=123456
#mha检测master服务器是否可以通的,1s一次
ping_interval=1
#主从同步的账号和密码
repl_user=rep
repl_password=123456
#ssh的账号,密码不需要,有私钥了
ssh_user=root
#通过脚本对vip进行切换,脚本放在mha服务器
master_ip_failover_script=/etc/mha/master_ip_failover
#表示mha通过-s指定的三个ip服务器,对master进行ping。当mha服务器ping不通master,此时mha服务断就ssh到slave服务器上去ping主数据库服务器,如果都不可以,那么确定master挂了
secondary_check_script=/usr/bin/masterha_secondary_check -s 192.168.209.128 -s 192.168.209.131 -s 192.168.209.132
[server1]
hostname=192.168.209.132
port=33061
#可选举为主
candidate_master=1
[server2]
hostname=192.168.209.131
port=33061
candidate_master=1
check_repl_delay=0 #默认情况下如果一个slave落后master 100M的relay logs的话,MHA将不会选择该slave作为一个新的master,因为对于这个slave的恢复需要花费很长时间,通过设置check_repl_delay=0,MHA触发切换在选择一个新的master的时候将会忽略复制延时,这个参数对于设置了candidate_master=1的主机非常有用,因为这个候选主机在切换的过程中一定是新的master
[server3]
hostname=192.168.209.128
port=33061
#不可选举为主
no_master=1
--------------------------------------------------
9.对ssh和数据库主从配置进行检测
#管理服务器执行,检查ssh是否可用
masterha_check_ssh --conf=/etc/mha/mysql_mha.cnf
#管理服务器执行,检测主从是否ok
masterha_check_repl --conf=/etc/mha/mysql_mha.cnf
#查看当前的master是否在运行种
masterha_check_status --conf=/etc/mha/mysql_mha.cnf
10.启动mha
先在master服务器手动添加一个vip
ifconfig eth0:0 192.168.209.199/24
启动mha
nohup masterha_manager --conf=/etc/mha/mysql_mha.cnf --remove_dead_master_conf --ignore_last_failover < /dev/null > /home/mysql_mha/mha.log 2>&1 &
--remove_dead_master_conf #该参数代表当发生主从切换后,老的主库的ip将会从配置文件中移除。
--manger_log #日志存放位置
--ignore_last_failover #在缺省情况下,如果MHA检测到连续发生宕机,且两次宕机间隔不足8小时的话,则不会进行Failover,之所以这样限制是为了避免ping-pong效应。该参数代表忽略上次MHA触发切换产生的文件。默认情况下,MHA发生切换后会在日志目录,也就是上面我设置的/data产生app1.failover.complete文件,下次再次切换的时候如果发现该目录下存在该文件将不允许触发切换,除非在第一次切换后收到删除该文件,为了方便,这里设置为--ignore_last_failover。
/home/mysql_mha/mha.log 存放mha启动日志
/home/mysql_mha/manager.log 存放mha业务日志,比如对主从进行切换的日志
11.模拟master挂了,然后mha自动把vip切换到slave,并且把slave提升为master,其他slave更改master源
192.168.209.131:关闭数据库
/usr/local/mysql/bin/mysqladmin -uroot -p123456 shutdown
1.数据库关闭完毕后,去192.168.209.128这个mha服务器
ps -ef|grep mha 查看mha是否已经关闭(master切换完成后,mha是会自动关闭的)
2.192.168.209.128 进入数据库查看master是否已经切换
mysql -uroot -p123456
show slave status\G
3.192.168.209.132 查看vip是否已经切换过来,查看自己是否为主
ip a #查看vip是否有了
mysql -uroot -p123456
show slave status\G
主从新起起来,此时这个主要作为从,从原来的从同步数据过来
192.168.209.131 起来后,手动切换为192.168.209.132的从,开始同步数据
当192.168.209.131成为192.168.209.132的从后,我们才可以再次启动mha,而且这次启动要加一个参数
-------------------------
nohup masterha_manager -ignore_last_failover --conf=/etc/mha/mysql_mha.cnf > /home/mysql_mha/manager.log 2>&1 &
-ignore_last_failover #忽略上一次的切换,如果不加这个参数,再次发送切换,mha就会出现问题,要你手动进行切换
--------------------------------
vip切换脚本(/etc/mha/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.209.199';
my $brdc = '192.168.209.255';
my $ifdev = 'eth0';
my $key = '0';
my $ssh_start_vip = "/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 = "/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 \"`;
}
sub stop_vip() {
return 0 unless ($ssh_user);
`ssh $ssh_user\@$orig_master_host \" $ssh_stop_vip \"`;
}
sub usage {
"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";
}