基于 MHA 高可用的 MySQL
功能
1、监控主数据库服务器是否可用
2、当主DB不可用时,从多个从服务器中选出新的主数据库服务器
3、提供了主从切换和故障转移功能(可以与半同步复制结合,最大程度的保证数据的完整性)
主从切换过程
1、尝试从出现故障的主数据库保存二进制日志
2、从多个备选从服务器中选出新的备选主数据库(用户可指定不参与选择的数据库)
3、在备选主服务器和其它从服务器之间同步差异二进制数据
4、新主服务器应用从原主DB服务器上保存的二进制日志(若主DB的二进制保存下来) 注:重复的主键等会使MHA停止进行故障转移
5、备选主DB服务器更新为新的主DB,并更改虚拟IP
6、迁移集群中的其它从DB作为新的主DB的从服务器
架构(支持基于GTID的复制)
步骤
1、配置集群中所有主机的SSH免认证登录(比如故障转移过程中保存原主服务器二进制日志,配置虚拟IP地址等)
2、安装MHA-node软件包(所有节点均安装)和MHA-manager(监控节点安装)软件包
命令:yum -y install perl-Config-Tiny.noarch
perl-Time-HiRes.x86_64
perl-Parallel-ForkManager
perl-Log-Dispatch-Per.noarch
perl-DBD-MySQL ncftp
3、建立主从复制集群
4、配置MHA管理节点
使用masterha_check_ssh:检查ssh免认证登录
使用masterha_check_repl :检查复制链路
5、启动并测试MHA服务
实例
1、建立基于GTID复制的集群
2、开启ssh免登录认证
ssh-keygen #开启ssh密钥
ssh-copy-id -i /root/.ssh/id_rsa -p 22 root@192.168.71.244|223|220 #复制rsa到集群中的所有服务器(互相免登录)
ssh root@192.168.71.244 #验证是否开启成功
3、下载node和manager安装包(wget [url])和安装perl的支持包(yum -y install perl-DBD-MySQL ncftp per-DBI.x86)
4、安装node (所有节点)
rpm -ivh mha4mysql-node-0.58-0.el7.centos.noarch.rpm
5、安装manager软件包和安装perl支持包(监控节点)
yum -y install perl-Config-Tiny.noarch #安装监控依赖
perl-Time-HiRes.x86_64
perl-Parallel-ForkManager
perl-Log-Dispatch-Per.noarch
perl-DBD-MySQL ncftp
rpm -ivh mha4mysql-manager-0.58-0.el7.centos.noarch.rpm #安装监控软件
6、配置MHA (配置监控节点即可)
mkdir -p /etc/mha #创建MHA配置目录
mkdir -p /home/mysql_mha #创建MHA的工作目录
vim /etc/mha/mysql_mha.cnf(见附件1) #建立配置文件
7、配置master_ip_failover(见附件2) 并chmod +x /usr/bin/master_ip_failover#变成可执行文件
8、检验ssh登录
masterha_check_ssh --conf = /etc/mha/mysql_mha.cnf(在监控服务器中运行)
9、检验repl通道
masterha_check_repl --conf = /etc/mha/mysql_mha.cnf(在监控服务器中运行)
10、运行mha
nohup masterha_manager --conf=/etc/mha/mysql_mha.cnf --remove_dead_master_conf --ignore_last_failover < /dev/null > /home/mysql_mha/manager.log 2>&1 & #放在后台运行
11、手动配置虚拟IP(在主中配置)
ifconfig eth0:1 192.168.71.90/24 #ip addr 查看ip
12、测试(查看虚拟IP和复制链路)
关闭主,查看从的复制链路和虚拟IP
备注:
#停止MHA
masterha_stop --conf=/etc/mha/mysql_mha.cnf [--remove_dead_master_conf ]--ignore_last_failover < /dev/null > /home/mysql_mha/manager.log 2>&1
#开始MHA
nohup masterha_manager --conf=/etc/mha/mysql_mha.cnf [--remove_dead_master_conf] --ignore_last_failover < /dev/null > /home/mysql_mha/manager.log 2>&1 &
--remove_dead_master_conf:删除失败配置
若M宕机后,MHA会自动切换
若M重新恢复时,需要再次手动配置主动
CHANGE MASTER TO MASTER_HOST='192.168.71.244', MASTER_PORT=3306, MASTER_AUTO_POSITION=1, MASTER_USER='repl', MASTER_PASSWORD='123456';
MHA常用命令
masterha_manager --conf=/etc/mha/mysql_mha.cnf #开启MHA manager
masterha_check_status --conf=/etc/mha/mysql_mha.cnf #检查MHA运行状态
masterha_check_repl --conf=/etc/mha/mysql_mha.cnf #检查复制健康状态
masterha_stop --conf=/etc/mha/mysql_mha.cnf #停止MHA manager运行
masterha_conf_host --command=add--conf=/etc/mha/mysql_mha.cnf --hostname=db101 --params="no_master=1;ignore_fail=1" #在配置文件中添加或移除host --block 移除
masterha_check——ssh --conf=/etc/mha/mysql_mha.cnf #ssh认证检查
【附件1】 mysql_mha.cnf:
[server default]
user = mha
password = 123456
manager_workdir = /home/mysql_mha
manager_log = /home/mysql_mha/manager.log
remote_workdir = /home/mysql_mha
ssh_user = root
repl_user = repl
repl_password = 123456
ping_interval =1
master_binlog_dir = /usr/local/mysql/log/mysql-bin
master_ip_failover_script = /usr/bin/master_ip_failover
#master_ip_online_change_script= /usr/bin/master_ip_online_change
secondary_check_script = /usr/bin/masterha_secondary_check -s 192.168.71.223 -s 192.168.71.244 -s 192.168.71.220
[server1]
hostname = 192.168.71.244
candidate_master = 1
[server2]
hostname = 192.168.71.223
candidate_master = 1
[server3]
hostname = 192.168.71.220
no_master = 1
【附件2】master_ip_failover
#!/usr/bin/env perl
use strict;
use warnings FATAL => 'all';
use Getopt::Long;
my (
$command,
$orig_master_host,$orig_master_ip,$orig_master_port, $orig_master_ssh_port,
$ssh_user,
$new_master_host,$new_master_ip, $new_master_port, $new_master_user,$new_master_password,$new_master_ssh_port
);
my $vip = '192.168.71.90/24';
my $key = '1';
my $ssh_start_vip = "sudo /sbin/ifconfig eth0:$key $vip";
my $ssh_stop_vip = "sudo /sbin/ifconfig eth0:$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,
'orig_master_ssh_port=i' => \$orig_master_ssh_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,
'new_master_ssh_port=i' => \$new_master_ssh_port
);
exit &main();
sub main {
$ssh_user = defined $ssh_user ? $ssh_user : 'root';
print "\n\nIN SCRIPT TEST ==== $ssh_user | $ssh_stop_vip == $ssh_user | $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_port 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";
}
【附件3】 report_script 邮箱通知
#!/usr/bin/perl
use strict;
use warnings FATAL => 'all';
use Email::Simple;
use Email::Sender::Simple qw(sendmail);
use Email::Sender::Transport::SMTP::TLS;
use Getopt::Long;
my ( $dead_master_host, $new_master_host, $new_slave_hosts, $subject, $body );
my $smtp='smtp.qq.com';
my $mail_from='xxx@qq.com';
my $mail_user='xxx@qq.com';
#邮箱授权码不是密码 邮箱授权码获取方式可以百度
my $mail_auth_pass='xxxxxx';
my $mail_to='xxxxxxxxxx';
GetOptions(
'orig_master_host=s' => \$dead_master_host,
'new_master_host=s' => \$new_master_host,
'new_slave_hosts=s' => \$new_slave_hosts,
'subject=s' => \$subject,
'body=s' => \$body,
);
my $transport = Email::Sender::Transport::SMTP::TLS->new(
host => $smtp,
port => 25,
username => $mail_user,
password => $mail_auth_pass,
);
my $message = Email::Simple->create(
header => [
From => $mail_from,
To => $mail_to,
Subject => $subject,
],
body => $body,
);
sendmail( $message, {transport => $transport} );
exit 0;
【附图1】MHA的配置参数
【附图2】masterha_check_ssh --conf = /etc/mha/mysql_mha.cnf 结果:
【附图3】masterha_check_repl --conf=/etc/mha/mysql_mha.cnf 结果:
本作品采用《CC 协议》,转载必须注明作者和本文链接