MHA据说是日本专家使用perl编写的MySQL数据库故障切换高可用方案。
所谓高可用,就是在单位时间区间内故障时间非常短,并在短时间内恢复服务,数据损失最小。
不过需要说明的是,使用高可用方案,故障时间越短,恢复越快,数据损失越小,你付出的代价也会约高。
建议根据需要和所能承担的成本进行评估,指定高可用实施方案。
1.MHA基本配置规格
一般来说最少需要MySQL一主二从,不过据说阿里云已经进行了改进一主一从也可以。
管理节点可以放在单独的服务器也可以放在一台从库服务器上。
建议使用MySQL5.7以上的较新版本,CentOS7或Debian9以上版本。
需要注意的是MHA版本之间有差异,mha4mysql-node-0.56-0.el6.noarch.rpm需要跟MySQL5.6配合使用。mha4mysql-node-0.58-0.el7.noarch.rpm跟MySQL5.7以上版本配合使用。
本配置文档使用的是,mha4mysql-node-0.56-0.el6.noarch.rpm和MySQL5.6。
2.配置方法简述
2.1环境
3台虚拟机,一主二从,管理节点放在从2上。
192.168.0.110(主)
192.168.0.112(从1)
192.168.0.111(从2+管理节点)
系统:CentOS7
数据库:MySQL5.6
Perl已经安装
2.2准备工作1-ssh免密设置
三台服务器之间需要相互可以免密访问(如果是独立的管理节点,需要管理节点可访问各数据库服务器,反向不需要)
以其中一台为例执行如下:
Ssh-keygen –t rsa
ssh-copy-id -i /root/.ssh/id_rsa [email protected]
ssh-copy-id -i /root/.ssh/id_rsa [email protected]
ssh-copy-id -i /root/.ssh/id_rsa [email protected]
执行命令检测ssh远程执行:
ssh root@[email protected] 'ls /'
其他服务器同样设置远程免密
2.3准备工作2-设置主机名和本机解析
建议给主库设置主机名为为master,从库名设置为slave01、slave02
主要是看着比较清楚,利于管理。
设置命令:
hostname sethostname master
主机名设置完毕,在/etc/hosts解析所有主机名
2.4安装mysql以及配置主从关系
安装MySQL5.6和主从配置本文不再赘述。
需要说明的是,安装半同步插件,在MySQL环境内主库和从执行如下:
install plugin rpl_semi_sync_master soname 'semisync_master.so';
set global rpl_semi_sync_master_enabled=1;
set global rpl_semi_sync_master_timeout=1000;
修改my.cnf添加如下:
rpl_semi_sync_master_enabled=1
rpl_semi_sync_master_timeout=1000
在MySQL环境内从库执行如下:
install plugin rpl_semi_sync_slave soname 'semisync_slave.so';
set global rpl_semi_sync_slave_enabled=1;
配置文件比主库多一条:
rpl_semi_sync_slave_enabled=1
创建复制用的数据库账户,主库和备用主库允许各从库访问。
例如:grant replication slave on *.* to slave001@'192.168.0.%' identified by '123456';
配置完毕后测试主从复制是否正常。在从库执行:
show slave status \G
2.5安装依赖包
yum install perl-Config-Tiny perl-Log-Dispatch perl-Time-HiRes perl-Parallel-ForkManager
yum install perl-DBD-MySQL
管理节点(即本例从2)安装如下:
wget ftp://rpmfind.net/linux/dag/redhat/el6/en/x86_64/dag/RPMS/perl-Mail-Sender-0.8.16-1.el6.rf.noarch.rpm
wget ftp://rpmfind.net/linux/dag/redhat/el6/en/x86_64/dag/RPMS/perl-Mail-Sendmail-0.79-1.2.el6.rf.noarch.rpm
rpm -ivh perl-Mail-Sender-0.8.16-1.el6.rf.noarch.rpm
rpm -ivh perl-Mail-Sendmail-0.79-1.2.el6.rf.noarch.rpm
2.6安装MHA
在所有服务安装:
rpm -ivh mha4mysql-node-0.56-0.el6.noarch.rpm
在管理节点安装:
rpm -ivh mha4mysql-manager-0.56-0.el6.noarch.rpm
以上包为0.56,如果是0.58最后检查配置时,会报错,类似下面的日式:
DBD::mysql::st execute failed: Unknown system variable 'super_read_only' at /usr/share/perl5/vendor_perl/MHA/SlaveUtil.pm line 245.
另外,0.56的包现在比较难找了,有些站点提供下载但是需要付费。
2.7测试MHA配置
检查ssh
masterha_check_ssh --conf=/etc/mha/app1.cnf
检查当前配置
masterha_check_repl --conf=/etc/mha/app1.cnf
文件 /etc/mha/app1.cnf需要自行创建,下面给一个例子。
[server default]
manager_log=/var/log/mha/app1/manager.log
manager_workdir=/var/log/mha/app1
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_script
password=12345678
ping_interval=1
repl_password=123456
repl_user=mha_rep
ssh_user=root
user=root
[server1]
candidate_master=1
check_repl_delay=0
hostname=192.168.0.112
master_binlog_dir=/usr/local/mysql/data
[server2]
candidate_master=1
check_repl_delay=0
hostname=192.168.0.110
master_binlog_dir=/usr/local/mysql/data
[server3]
candidate_master=1
check_repl_delay=0
hostname=192.168.0.111
ignore_fail=1
master_binlog_dir=/usr/local/mysql/data
no_master=1
port=3306
提示1:master二进制文件没有在缺省路径找到,可以在app1.cnf设置master_binlog_dir
Failed to save binary log: Binlog not found from /var/lib/mysql! If you got this error at MHA Manager, please set "master_binlog_dir=/path/to/binlog_directory_of_the_master" correctly in the MHA Manager's configuration file and try again.
at /usr/bin/save_binary_logs line 123.
注意,所有mysql服务器的相关设置都需要修改,还有default的也需要
提示2:Can't exec "mysqlbinlog": No such file or directory at
意思是找不到mysqlbinlog,显然是路径问题。mysql因为安装路径不是其默认路径。
解决方法:ln -s /usr/local/mysql/bin/mysql /usr/local/bin/mysql &&ln -s /usr/local/mysql/bin/mysqlbinlog /usr/local/bin/mysqlbinlog
启动mha
nohup masterha_manager --conf=/etc/mha/app1.cnf --remove_dead_master_conf --ignore_last_failover < /dev/null > /var/log/mha/app1/manager.log 2>&1 &
检查状态
masterha_check_status --conf=/etc/mha/app1.cnf
关闭
masterha_stop --conf=/etc/mha/app1.cnf
查看日志
tail -f /var/log/mha/app1/manager.log
3.检测故障转移
关闭master的mysql
在从2进入mysql环境,执行show slave status \G
可以发现其master已经转移到从1
4.vip的转移
vip故障转移=需要单独的脚本来实现,在配置文件中master_ip_failover_script=/usr/local/bin/master_ip_failover配置了。
master_ip_failover脚本的实现从网上找了一个实例,调试通过,可参考使用。
#!/usr/bin/env perl
# Copyright (C) 2011 DeNA Co.,Ltd.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# 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
);
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 {
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 {
# updating global catalog, etc
$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 {
my $new_master_handler = new MHA::DBHelper();
# args: hostname, port, user, password, raise_error_or_not
$new_master_handler->connect( $new_master_ip, $new_master_port,
$new_master_user, $new_master_password, 1 );
## Set read_only=0 on the new master
$new_master_handler->disable_log_bin_local();
print "Set read_only=0 on the new master.\n";
$new_master_handler->disable_read_only();
## Creating an app user on the new master
print "Creating app user on the new master..\n";
FIXME_xxx_create_user( $new_master_handler->{dbh} );
$new_master_handler->enable_log_bin_local();
$new_master_handler->disconnect();
## Update master ip on the catalog database, etc
FIXME_xxx;
$exit_code = 0;
};
if ($@) {
warn $@;
# If you want to continue failover, exit 10.
exit $exit_code;
}
exit $exit_code;
}
elsif ( $command eq "status" ) {
# do nothing
exit 0;
}
else {
&usage();
exit 1;
}
}
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";
}
保存脚本并放指定目录下,在进行测试可以发现vip已经可以自动转移了。当然还有其他方法实现vip转移,这里不再描述。