香港服务器的MySQL之高可用组件MHA
云服务器
香港服务器的MySQL之高可用组件MHA
2026-01-21 09:49
香港服务器的MySQL之高可用组件MHA
1简介
MHA(MasterHighAvailability)是由日本人yoshinorim开发的一款成熟且开源的MySQL高可用程序,它实现了MySQL主从环境下MASTER宕机后能够自动进行单次故障转移的功能,其本身由perl语言编写,安装方便,使用简单
MHAMaster可以单独部署在一台独立的机器上管理多个master-slave集群,也可以部署在一台slave节点上
MHAManager主要运行一些工具,比如masterha_manager工具实现自动监控MySQLMaster和实现master故障切换,其它工具实现手动实现master故障切换、在线master转移、连接检查等
MHANode部署在所有运行MySQL的服务器上,无论是master还是slave。主要作用有三个
Ⅰ、保存二进制日志如果能够访问故障master,会拷贝master的二进制日志
II、应用差异中继日志从拥有最新数据的slave上生成差异中继日志,然后应用差异日志
III、清除中继日志在不停止SQL线程的情况下删除中继日志
MHA工作原理
从宕机崩溃的Master保存二进制日志事件(binlogevent);
识别含有最新更新的Slave;
应用差异的中继日志(relaylog)到其他Slave;
应用从Master保存的二进制日志事件;
提升一个Slave为新的Master;
使其他的Slave连接新的Master进行复制;
MHA数据补偿
当SSH能连接,从库对比主库GTID或者position号,立即将二进制日志保存至各个从节点并且应用(save_binary_logs)
当SSH不能连接,对比从库之间的relaylog的差异(apply_diff_relay_logs)
2环境部署
节点ip
主节点10.243.95.3
从节点110.243.95.4
从节点210.243.95.5
数据库复制一主两从架构,MHAnode部署在每个节点上,MHAmanager部署在从节点2上
2.1建立SSH互信
#各节点生成rsa密钥
ssh-keygen-trsa
#发送密钥至三台服务器实现互信
ssh-copy-idroot@10.243.95.3
ssh-copy-idroot@10.243.95.4
ssh-copy-idroot@10.243.95.5
2.2搭建主从复制
具体内容见上篇主从复制,注意mha57以下版本不支持GTID事务,需避雷,按需选择下面的部署方法
2.3安装依赖包
2.3.1MHA-0.57-el6版本
#1.所有节点安装以下依赖包
yum-yinstallperl-DBD-MySQLperl-ExtUtils-MakeMakerperl-CPAN
yuminstall-yperl-DBD-MySQLperl-Config-Tinyperl-Log-Dispatchperl-Parallel-ForkManagerperl-Time-HiRes
#2.所有节点安装mha-node包
rpm-ivhmha4mysql-node-0.57-0.el6.noarch.rpm
#3.管理节点安装mha-manage包
rpm-ivhmha4mysql-manager-0.57-0.el6.noarch.rpm
2.3.2MHA-0.55-el6版本
#1.解压mha包
unzip-umha_pack.zip
cdmha_pack/mha_pack/rhel6/mha2
#2.安装依赖
rpm-ivhperl-DBI-1.609-4.el6.x86_64.rpm
rpm-ivhperl-DBD-MySQL-4.013-3.el6.x86_64.rpm
rpm-ivhmha4mysql-node-0.54-0.el6.noarch.rpm
rpm-ivhperl-DBI-1.609-4.el6.x86_64.rpm
rpm-ivhperl-DBD-MySQL-4.013-3.el6.x86_64.rpm
rpm-ivhmha4mysql-node-0.54-0.el6.noarch.rpm
rpm-ivhperl-Config-Tiny-2.12-7.1.el6.noarch.rpm
rpm-ivhperl-TimeDate-1.16-11.1.el6.noarch.rpm
rpm-ivhperl-MailTools-2.04-4.el6.noarch.rpm
rpm-ivhperl-Email-Date-Format-1.002-5.el6.noarch.rpm
rpm-ivhperl-MIME-Types-1.28-2.el6.noarch.rpm
rpm-ivhperl-MIME-Lite-3.027-2.el6.noarch.rpm
rpm-ivhperl-Mail-Sender-0.8.16-3.el6.noarch.rpm
rpm-ivhperl-Mail-Sendmail-0.79-12.el6.noarch.rpm
rpm-ivhperl-Params-Validate-0.92-3.el6.x86_64.rpm
rpm-ivhperl-Log-Dispatch-2.27-1.el6.noarch.rpm
rpm-ivhperl-Parallel-ForkManager-0.7.9-1.el6.noarch.rpm
rpm-ivhperl-Time-HiRes-1.9721-127.el6.x86_64.rpm
rpm-ivhmha4mysql-manager-0.55-0.el6.noarch.rpm
2.4配置文件
新建mha配置文件:vi/etc/masterha/app1.cnf
[serverdefault]
#mysqlrootuserandpassword
user=root
password=123456
#mysqlloglocations
#master_binlog_dir=/mysql/data
#usertouseSSHaroundthecluster
ssh_user=root
#repluserandpassword
repl_user=repl
repl_password=123456
#workingdirectoryonthemanager
manager_log=/root/mha/log/manager.log
manager_workdir=/root/mha/log
#remote_workdir=/mysql/mha/log
#MHApinginterval
ping_interval=5
##scriptstosupportMHAfunctions
##secondary_check_script=/usr/bin/masterha_secondary_check-sremote_host1-sremote_host2
master_ip_failover_script=/root/mha/scripts/master_ip_failover
##shutdown_script=/usr/local/masterha/scripts/power_manager
##report_script=/usr/local/masterha/scripts/send_report
master_ip_online_change_script=/root/mha/scripts/master_ip_online_change
#masters
[server1]
hostname=10.243.95.3
port=3306
candidate_master=1
master_binlog_dir=/opt/mysql/binlog
remote_workdir=/root/mha/log
[server2]
hostname=10.243.95.4
port=3306
candidate_master=1
check_repl_delay=0
master_binlog_dir=/opt/mysql/binlog
remote_workdir=/root/mha/log
[server3]
hostname=10.243.95.5
port=3306
candidate_master=1
check_repl_delay=0
master_binlog_dir=/opt/mysql/binlog
remote_workdir=/root/mha/log
2.5切换脚本
1)创建一些目录
#建立mha的文件夹
mkdir-p/root/mha/conf
mkdir-p/root/mha/log
mkdir-p/root/mha/scripts
chmod-R777/root/mha/scripts
2)新建脚本
在线切换脚本
vi/root/mha/scripts/master_ip_online_change
#!/usr/bin/envperl
#Copyright(C)2011DeNACo.,Ltd.
#
#Thisprogramisfreesoftware;youcanredistributeitand/ormodify
#itunderthetermsoftheGNUGeneralPublicLicenseaspublishedby
#theFreeSoftwareFoundation;eitherversion2oftheLicense,or
#(atyouroption)anylaterversion.
#
#Thisprogramisdistributedinthehopethatitwillbeuseful,
#butWITHOUTANYWARRANTY;withouteventheimpliedwarrantyof
#MERCHANTABILITYorFITNESSFORAPARTICULARPURPOSE.Seethe
#GNUGeneralPublicLicenseformoredetails.
#
#YoushouldhavereceivedacopyoftheGNUGeneralPublicLicense
#alongwiththisprogram;ifnot,writetotheFreeSoftware
#Foundation,Inc.,
#51FranklinStreet,FifthFloor,Boston,MA02110-1301USA
##Note:Thisisasamplescriptandisnotcomplete.Modifythescriptbasedonyourenvironment.
usestrict;
usewarningsFATAL=>'all';
useGetopt::Long;
useMHA::DBHelper;
useMHA::NodeUtil;
useTime::HiResqw(sleepgettimeofdaytv_interval);
useData::Dumper;
my$_tstart;
my$_running_interval=0.1;
my(
$command,$ssh_user,$orig_master_host,$orig_master_ip,
$orig_master_port,$orig_master_user,$orig_master_password,
$new_master_host,$new_master_ip,$new_master_port,
$new_master_user,$new_master_password
);
my$vip='192.168.90.30';#writerVirtualIP
my$gw=`route|grepdefault|awk'{print\$2}'`;
chomp($gw);
my$interface='eth0';#networkinterface
my$ssh_start_vip="ipaddradd$vip/32dev$interface";
my$ssh_ping="arping-U-I$interface-s$vip$gw-c5";
my$ssh_stop_vip="ipaddrdel$vip/32dev$interface";
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_user=s'=>\$orig_master_user,
'orig_master_password=s'=>\$orig_master_password,
'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,
);
$ssh_user='root'unless($ssh_user);
exit&main();
subcurrent_time_us{
my($sec,$microsec)=gettimeofday();
my$curdate=localtime($sec);
return$curdate."".sprintf("%06d",$microsec);
}
subsleep_until{
my$elapsed=tv_interval($_tstart);
if($_running_interval>$elapsed){
sleep($_running_interval-$elapsed);
}
}
subget_threads_util{
my$dbh=shift;
my$my_connection_id=shift;
my$running_time_threshold=shift;
my$type=shift;
$running_time_threshold=0unless($running_time_threshold);
$type=0unless($type);
my@threads;
my$sth=$dbh->prepare("SHOWPROCESSLIST");