目录
一、MHA介绍
MHA
(
Master High Availability
)目前在
MySQL
高可用方面是一个相对成熟的解决方案,是一套优秀的作为
MySQL
高可用性环境下故障切换和主从提升的高可用软件。
在
MySQL
故障切换过程中,
MHA
能做到在
0~30
秒之内自动完成数据库的故障切换操作,并且在进行故障切换的过程中,
MHA
能在最大程度上保证数据的一致性,以达到真正意义上的高可用。
该软件由两部分组成:
MHA Manager
(管理节点)和
MHA Node
(数据节点)。
MHA Manager
可以单独部署在一台独立的机器上管理多个
master-slave
集群,也可以部署在一台
slave
节点上。
MHA Node
运行在每台
MySQL
服务器上,
MHA Manager
会定时探测集群中的
master
节点,当
master
出现故障时,它可以自动将最新数据的
slave
提升为新的
master
,然后将所有其他的
slave
重新指向新的
master
。整个故障转移过程对应用程序完全透明。
在
MHA
自动故障切换过程中,
MHA
试图从宕机的主服务器上保存二进制日志,最大程度的保证数据的不丢失,但这并不总是可行的。例如,如果主服务器硬件故障或无法通过
ssh
访问,
MHA
没法保存二进制日志,只进行故障转移而丢失了最新的数据。使用
MySQL 5.5
的半同步复制,可以大大降低数据丢失的风险。
MHA
可以与半同步复制结合起来。如果只有一个
slave
已经收到了最新的二进制日志,
MHA
可以将最新的二进制日志应用于其他所有的
slave
服务器上,因此可以保证所有节点的数据一致性。
目前
MHA
主要支持一主多从的架构,要搭建
MHA,
要求一个复制集群中必须最少有三台数据库服务器,一主二从,即一台充当
master
,一台充当备用
master
,另外一台充当从库,因为至少需要三台服务器,出于机器成本的考虑,淘宝也在该基础上进行了改造,淘宝
TMHA
已经支持一主一从。
MHA原理:
MHA
用于维持
MySQL Replication
中
master
库的高可用性,最大的特点是可以修复多个
slave
上的差异日志,最终使所有
slave
保持数据一致,然后从中选取一个充当新的
master
,并让其他
slave
指向它。
当
master
出现故障时,通过对比
slave
之间的
I/O thread
读取主库的
binlog
的
position
号,选取最接近的
slave
作为备胎(被选主库),其它从库通过与备胎对比,生成差异的中继日志,在备胎上运用从原来的
master
保存的
binlog
,同时将备胎提升为
master
。最后在其他
slave
上运用相应的差异中继日志,并从新的
master
开始复制。
MHA优点:
①
故障切换时,自动判断哪个从库与主库离的最近,并切换到该从库
②
支持
binlog server
,提高
binlog
的传送效率
③
结合半同步功能,确保故障切换时数据不丢失
二、MHA搭建
1.
环境准备
|
|
|
|
192.168.16.18 |
centos8-min8 |
CentOS Linux release 8.2.2004 |
master |
192.168.16.19 |
centos8-min9 |
CentOS Linux release 8.2.2004 |
slave1 |
192.168.16.20 |
centos8-min10 |
CentOS Linux release 8.2.2004 |
slave2+ manager |
由于安装MHA-Node过程中发现centos8并不能安装MHA-Node,所以将操作系统重装换成centos7
|
|
|
|
|
centos7-min-ha1 |
|
master |
|
centos7-min-ha2 |
|
slave1 |
|
centos7-min-ha3 |
|
slave2+ manager |
2.MHA
下载与MySQL安装
> MHA下载地址
wget
https://github.com/yoshinorim/mha4mysql-node/releases/download/v0.58/mha4mysql-node-0.58.tar.gz
- MySQL官网下载MYSQL:https://downloads.mysql.com/archives/community/
目前MYSQL官网并未提供redhat8版本的MYSQL产品
centos8-min8:
centos8-min9:
centos8-min10:
- MySQL安装
使用mysql自动化安装脚本在三台服务器上安装mysql,自动化安装脚本可参考如下:
###采用二进制安装包安装MySQL###
###############################
#!/bin/bash
## The 3 messages you need to update according to your package
dir_package='/opt'
install_package=${dir_package}'/mysql-5.7.24-el7-x86_64.tar.gz'
package_version='mysql-5.7.24'
## The default linux system version is Redhat/CentOS7
clear
echo "=========================================================================="
echo "A tool to auto-compile & install $package_version on Redhat/CentOS7 Linux "
echo "=========================================================================="
## 1. check the integrity of your mysql package
echo ">>Step1: md5sum 验证包的完整性"
echo `md5sum $install_package` | awk '{print $1}'
echo "If the md5sum is the same with the one obtained from https://downloads.mysql.com/archives/community/ ?"
read -p "(Please input yes or no):" checkmysql
case "$checkmysql" in
yes|y|Y|YES|yeS|yES|Yes|YeS|yEs|YEs)
checkmysql='y'
echo "安装包完整,可以开始安装"
;;
*)
echo "安装包不完整,请重新获取安装包"
checkmysql='n'
exit
esac
## 2. preparations for mysql installation
echo ">>Step2: mysql安装准备中..."
package_tar_name=${install_package##*/}
package_name=${package_tar_name%%.tar*}
## decompress the install package
tar zxvf $package_tar_name -C ${dir_package}/
cd ${dir_package}/
mv ${package_name} mysql
## create user mysql
useradd mysql
## create some directories needed by this installation
cd ${dir_package}/mysql/
touch my.cnf
mkdir -p data
mkdir -p log
mkdir -p mylog
mkdir -p pid
mkdir -p socket
mkdir -p tmp
chown -R mysql:mysql ${dir_package}/mysql
## assign the port for mysql installation
read -p "Tell me a viable port you'd like to install mysql (the default port is 3306):" port
if [ ! $port ];then
mport=3306
elif [ !`$port -eq 3306` ];then
mport=$port
fi
echo "The port="$mport
## define the my.cnf
cat >>${dir_package}/mysql/my.cnf<<EOF
[client]
port = $mport
socket = ${dir_package}/mysql/socket/mysqld-T-prod-$mport.sock
default-character-set=utf8
[mysqld]
user = mysql
port = $mport
socket = ${dir_package}/mysql/socket/mysqld-T-prod-$mport.sock
datadir = ${dir_package}/mysql/data
basedir = ${dir_package}/mysql
server-id = 1
log-bin = ${dir_package}/mysql/mylog/mysql-bin-T-prod-$mport
sync-binlog=1
tmpdir = ${dir_package}/mysql/tmp
[mysqld_safe]
pid-file = ${dir_package}/mysql/pid/mysql-T-prod-$mport.pid
log-error = ${dir_package}/mysql/log/mysql-T-prod-$mport.err
EOF
## Update ${dir_package}/mysql/support-files/mysql.server for mysql start | stop
cd ${dir_package}/mysql/support-files
sed -i "/^datadir=/{s/$/\\${dir_package}\\/mysql\\/data/}" mysql.server ##datadir=${dir_package}/mysql/data
sed -i "/^basedir=/{s/$/\\${dir_package}\\/mysql/}" mysql.server ##basedir=${dir_package}/mysql
sed -i "/^mysqld_pid_file_path=/{s/$/\\${dir_package}\\/mysql\\/pid\\/mysql-T-prod-$mport.pid/}" mysql.server
#default_conf="conf=/etc/my.cnf"
#conf="conf=/opt/mysql57/my.cnf"
#sed -i "s/${default_conf}/${conf}/g" mysql.server
sed -i "s/\\/etc\\/my.cnf/\\${dir_package}\\/mysql\\/my.cnf/g" mysql.server ##conf=${dir_package}/mysql/my.cnf
## 3. initial and start mysql installation
###function installMysql(){
echo ">>Step3: 开始安装$package_version"
echo "We are about to install $package_version, please wait..."
echo ">>Step3-1: 数据库初始化"
${dir_package}/mysql/bin/mysqld --defaults-file=${dir_package}/mysql/my.cnf --initialize --user=mysql --basedir=${dir_package}/mysql --datadir=${dir_package}/mysql/data
echo "=======Very important!! Please remember the password of root if the initial is successful=========="
echo ">>Step3-2: 启动数据库"
## 使用mysql用户启动mysql服务(如果mysql没有启动,请手动启动哈)
su - mysql -s /bin/bash -c "${dir_package}/mysql/support-files/mysql.server start"
## 检查mysql启动的进程
if [ `ps -ef | grep mysql | grep -v grep | wc -l` -eq 0 ]
then
echo "Mysql started failed"
else
echo "Mysql started successfully"
fi
###}
##installMysql 2&>1 | tee ${dir_package}/mysql/installMysql.log
## 4. what you need to do after mysql installation
## ① 设置mysql环境变量
#echo `export MYSQL_HOME=${dir_package}/mysql` >> /home/mysql/.bashrc
#echo `export PATH=$PATH:$MYSQL_HOME/bin`>> /home/mysql/.bashrc
#source /home/mysql/.bashrc
## ② 使用临时root密码登录mysql并修改root密码
#su - mysql
#mysql -uroot -p
#mysql> alter user user() identified by '123456';
定制my.cnf
[root@centos8-min8 mysql]# cat my.cnf
[client]
port = 3306
socket = /root/mysql/socket/mysqld-T-prod-3306.sock
default-character-set=utf8
[mysqld]
user = mysql
port = 3306
socket = /root/mysql/socket/mysqld-T-prod-3306.sock
datadir = /root/mysql/data
basedir = /root/mysql
tmpdir = /root/mysql/tmp
##server-id = 1618
##log-bin = /root/mysql/mylog/mysql-bin-T-prod-3306
##sync-binlog=1
##relay_log = /root/mysql/mylog/relay-log-T-prod-3306
###log_slave_updates=1
#GTID
gtid_mode=on
enforce_gtid_consistency=on
server-id=1618 #
每一台服务器的server-id应该不同
#binlog
log-bin=/root/mysql/mylog/mysql-bin-T-prod-3306
sync-binlog=1
log_slave_updates=1
binlog_format=row
#relay log
skip_slave_start=1
[mysqld_safe]
pid-file = /root/mysql/pid/mysql-T-prod-3306.pid
log-error = /root/mysql/log/mysql-T-prod-3306.err
[root@centos8-min8 ~]# mysql -uroot -p
mysql: error while loading shared libraries: libncurses.so.5: cannot open shared object file: No such file or directory
[root@centos8-min8 ~]# yum -y install libncurses*
[root@centos8-min10 ~]# mysql -uroot -p
Enter password:
mysql> alter user user() identified by ‘123456’;
3.
配置三台服务器基本信息
① 将Hostname与IP进行关联
[root@centos7-min-ha1 ~]# cat /etc/hosts
192.168.16.21 centos7-min-ha1
192.168.16.22 centos7-min-ha2
192.168.16.23 centos7-min-ha3
[root@centos7-min-ha1 ~]# scp /etc/hosts
root@192.168.16.22:/etc/hosts
[root@centos7-min-ha1 ~]# scp /etc/hosts
root@192.168.16.23:/etc/hosts
② 配置SSH免密登录
[root@centos8-min8 ~]# ssh -V
OpenSSH_8.0p1, OpenSSL 1.1.1c FIPS 28 May 2019 —— CentOS8.2 ssh默认版本
[root@centos7-min-ha1 ~]# ssh -V
OpenSSH_7.4p1, OpenSSL 1.0.2k-fips 26 Jan 2017 —— CentOS7.8 ssh默认版本
/root/.ssh
[root@centos8-min8 ~]# ssh-keygen ——生成公私钥对
[root@centos8-min8 .ssh]# ll
total 12
-rw——-. 1 root root 2602 Feb 2 17:35 id_rsa
-rw-r–r–. 1 root root 571 Feb 2 17:35 id_rsa.pub
-rw-r–r–. 1 root root 350 Feb 2 13:52 known_hosts
[root@centos8-min8 .ssh]# ssh-copy-id -i /root/.ssh/id_rsa.pub 192.168.16.19 ——把公钥拷贝到其它机器
[root@centos8-min8 .ssh]# ssh-copy-id -i /root/.ssh/id_rsa.pub 192.168.16.20
拷贝完毕之后可在对应机器上查看到公钥信息
[root@centos8-min9 .ssh]# cat /root/.ssh/authorized_keys
[root@centos8-min8 .ssh]# ssh 192.168.16.19 ——min8可免密登录到保存了其公钥的机器
Activate the web console with: systemctl enable –now cockpit.socket
Last login: Tue Feb 2 13:04:52 2021 from 192.168.16.1
[root@centos8-min9 ~]#
同理配置min9和min10两台机器的ssh免密登录即可
4.
选择主从模式
>
经典主从复制模式
使用
binlog+pos
开启复制
,
在从库指定主库的
binlog_file
和
log_pos
MYSQL主备复制可参考 :http://t.csdn.cn/QOKci
> GTID
模式
开启GTID,无需找到binlog和pos点,直接change master to master_auto_postion=1即可,它会自动寻找同步
①
GTID
的概述:
1
、全局事物标识:
global transaction identifieds
。
2
、
GTID
事物是全局唯一性的,且一个事务对应一个
GTID
。
3
、一个
GTID
在一个服务器上只执行一次,避免重复执行导致数据混乱或者主从不一致。
4
、
GTID
用来代替
classic
的复制方法,不在使用
binlog+pos
开启复制。而是使用
master_auto_postion=1
的方式自动匹配
GTID
断点进行复制。
5
、
MySQL-5.6.5
开始支持的,
MySQL-5.6.10
后开始完善。
6
、在传统的
slave
端,
binlog
是不用开启的,但是在
GTID
中,
slave
端的
binlog
是必须开启的,目的是记录执行过的
GTID
(强制)。
②
GTID
的组成部分:
前面是
server_uuid
:后面是一个序列号
例如:
server_uuid
:
sequence number
7800a22c-95ae-11e4-983d-080027de205a:10
UUID
:每个
mysql
实例的唯一
ID
,由于会传递到
slave
,所以也可以理解为源
ID
。
Sequence number
:在每台
MySQL
服务器上都是从
1
开始自增长的序列,一个数值对应一个事务。
③
GTID
比传统复制的优势:
1
、更简单的实现
failover
,不用以前那样在需要找
log_file
和
log_Pos
。
2
、更简单的搭建主从复制。
3
、比传统复制更加安全。
4
、
GTID
是连续没有空洞的,因此主从库出现数据冲突时,可以用添加空事物的方式进行跳过。
④
GTID
的工作原理:
1
、
master
更新数据时,会在事务前产生
GTID
,一同记录到
binlog
日志中。
2
、
slave
端的
i/o
线程将变更的
binlog
,写入到本地的
relay log
中。
3
、
sql
线程从
relay log
中获取
GTID
,然后对比
slave
端的
binlog
是否有记录。
4
、如果有记录,说明该
GTID
的事务已经执行,
slave
会忽略。
5
、如果没有记录,
slave
就会从
relay log
中执行该
GTID
的事务,并记录到
binlog
。
6
、在解析过程中会判断是否有主键,如果没有就用二级索引,如果没有就用全部扫描。
⑤
使用
GTID
搭建
mysql
的主从复制的主要参数:
[mysqld]
#GTID:
gtid_mode=on
enforce_gtid_consistency=on
server_id=2003306 #
每个实例的
server_id
都要不一样
#binlog
log-bin=mysqlbin
log-slave-updates=1 #
允许下端接入
slave
binlog_format=row
#
强烈建议,其他格式可能造成数据不一致
#relay log
skip_slave_start=1
注意:建议使用
mysql-5.6.5
以上的最新版本。
⑥
启动
GTID
的两种方法:
方法一、
1
、如果是在已经跑的服务器,你需要重启一下
mysql server
。
2
、启动之前,一定要先关闭
master
的写入,保证所有
slave
端都已经和
master
端数据保持同步。
3
、所有
slave
需要加上
skip_slave_start=1
的配置参数,避免启动后还是使用老的复制协议。
方法二、
1
、如果是新搭建的服务器,直接启动就行了。
⑦
master-slave
搭建的注意事项
(一)、使用
GTID
的方式,把
salve
端挂载
master
端:
1
、启动以后最好不要立即执行事务,而是先
change master
上。
2
、然后在执行事务,当然知不是必须的。
3
、使用下面的
sql
切换
slave
到新的
master
。
stop slave;
change master to
master_host = 192.168.100.200,
master_port = 3306,
master_user = abobo,
master_password=123,
master_auto_position = 1;
(
二
)
、如果给已经运行的
GTID
的
master
端添加一个新的
slave
有两种方法:
方法一、适用于
master
也是新建不久的情况。
1
、如果你的
master
所有的
binlog
还在。可以选择类似于上面的方法,安装
slave
,直接
change master to
到
master
端。
2
、原理是直接获取
master
所有的
GTID
并执行。
3
、优点:简单方便。
4
、缺点:如果
binlog
太多,数据完全同步需要时间较长,并且
master
一开始就启用了
GTUD
。
方法二、适用于拥有较大数据的情况。(推荐)
1
、通过
master
或者其他
slave
的备份搭建新的
slave
。(看第三部分)
2
、原理:获取
master
的数据和这些数据对应的
GTID
范围,然后通过
slave
设置
@@global.gtid_purged
跳过备份包含的
gtid
。
3
、优点:是可以避免第一种方法的不足。
4
、缺点:相对来说有点复杂。
5.
搭建主从环境
① 环境说明
本次实验搭建一主两从环境,使用的版本是5.7.28,基于GTID+row+增强半同步模式
GTID —— Global Transaction Identifier
复制格式 —— 推荐使用row格式,statement和mixed格式坑太多。
增强半同步 —— rpl_semi_sync_master_wait_point = AFTER_SYNC
#5.7中默认已经是after_sync
② 在三台MySQL服务器上创建主从复制账号和管理账号
#创建主从复制账号
[mysql@centos8-min8 support-files]$ mysql -uroot -p
Enter password: 123456
mysql> create user ‘gtid’@’192.168.16.%’ identified by ‘gtid123’;
mysql> grant replication slave on *.* to ‘gtid’@’192.168.16.%’;
mysql> flush privileges;
#创建管理账号
mysql> create user ‘manage’@’192.168.16.%’ identified by ‘manage123’;
mysql> grant all privileges on *.* to ‘manage’@’192.168.16.%’;
mysql> flush privileges;
mysql> select Host,User from mysql.user;
③ 在主库上复制数据到所有从库,完成在某个时刻GTID的同步
[mysql@centos8-min8 mysql]$ mysqldump –single-transaction -uroot -p -A > all.sql
Enter password: 123456
[mysql@centos7-min-ha1 mysql]$ mysqldump –all-databases –triggers –routines –events -uroot -p -A > all.sql
Enter password:
[mysql@centos7-min-ha1 mysql]$
[mysql@centos7-min-ha1 mysql]$ ll
total 1132
-rw-rw-r–. 1 mysql mysql 848521 Feb 23 14:12 all.sql
[root@centos8-min8 mysql]# scp all.sql 192.168.16.19:/root/mysql/
[root@centos8-min8 mysql]# scp all.sql 192.168.16.20:/root/mysql/
④ 从各从库恢复备份并配置主从复制,开启主从同步
[mysql@centos8-min9 mysql]$ mysql -uroot -p < all.sql
[mysql@centos8-min10 mysql]$ mysql -uroot -p < all.sql
> 问题追踪
主要原因是之前的数据库里面配置了主从,再导出的时候一起导出来了
,
所以导入时会出现这个问题。
解决办法:在导入的服务器重置一下主数据库服务器,再重新导入sql文件即可
配置文件my.cnf修改(主从服务器配置除server-id之外其余信息一致):
注意:每台MySQL服务器的server-id必须是不一样的!
[mysql@centos7-min-ha1 root]$ vi mysql/my.cnf
[client]
port = 3306
socket = /root/mysql/socket/mysqld-T-prod-3306.sock
default-character-set=utf8
[mysqld]
user = mysql
port = 3306
socket = /root/mysql/socket/mysqld-T-prod-3306.sock
datadir = /root/mysql/data
basedir = /root/mysql
tmpdir = /root/mysql/tmp
##server-id = 1620
##log-bin = /root/mysql/mylog/mysql-bin-T-prod-3306
##sync-binlog=1
##relay_log = /root/mysql/mylog/relay-log-T-prod-3306
###log_slave_updates=1
#GTID
gtid_mode=on
enforce_gtid_consistency=on
server-id=1621
#binlog
log-bin=/root/mysql/mylog/mysql-bin-T-prod-3306
sync-binlog=1
log_slave_updates=1
binlog_format=row
#relay log
skip_slave_start=1
[mysqld_safe]
pid-file = /root/mysql/pid/mysql-T-prod-3306.pid
log-error = /root/mysql/log/mysql-T-prod-3306.err
[root@centos7-min-ha2 ~]# vi mysql/my.cnf
#GTID
gtid_mode=on
enforce_gtid_consistency=on
server-id=1622
[mysql@centos7-min-ha3 mha]$ vi /root/mysql/my.cnf
#GTID
gtid_mode=on
enforce_gtid_consistency=on
server-id=1623
重启主从mysql服务并查看gtid模式启用状态
[mysql@centos8-min8 mysql]$ support-files/mysql.server restart
主库master状态:
从库192.168.16.22同步主库master:
mysql> change master to
->
master_host=’192.168.16.21′,
-> master_port=3306,
-> master_user=’gtid’,
-> master_password=’gtid123′,
-> master_auto_position=1;
从库192.168.16.20同步主库master:
- 问题追踪
1. gtid_mode未开启
这个参数
gtid_mode
是一个单项的修改过程,也就是说从
off
到
on
,需要经过中间的
OFF <-> OFF_PERMISSIVE <-> ON_PERMISSIVE <-> ON
过程,而相邻的两个状态之间可以相互转换。否则会出错。
[mysqld]
gtid_mode=on
enforce_gtid_consistency=on
2. slave IO
进程通信连接不上
开放
mysql
端口或者关闭防火墙即可
[root@centos8-min9 ~]# systemctl stop firewalld
[root@centos8-min9 ~]# systemctl disable firewalld
[root@centos8-min9 ~]# systemctl status firewalld
服务器挂掉之后MySQL主从同步失败,需要重启slave
6.
安装MHA-Node节点
在所有节点上安装数据节点
安装MySQL依赖的perl环境
①安装
epel
源
yum install -y epel-release
②安装
perl
yum install perl-DBD-MySQL
yum install perl-Config-Tiny
yum install perl-Log-Dispatch
yum install perl-Parallel-ForkManager
yum install perl-Params-Validate
③安装
mha-node
tar -zxf mha4mysql-node-0.58.tar.gz
cd mha4mysql-node-0.58/
yum install perl-CPAN* -y
perl Makefile.PL
make && make install
- 问题追踪
执行yum命令失败,服务器不能访问外网
Cannot find a valid baseurl for repo: base/7/x86_64
添加DNS到网卡配置并重启网络
[root@centos8-min8 ~]# yum install perl-DBD-MySQL -y
解压mha4mysql-node-0.58.tar.gz 并安装 per-cpan
[root@centos8-min8 ~]# tar -zxf mha4mysql-node-0.58.tar.gz
[root@centos8-min8 ~]# cd mha4mysql-node-0.58/
[root@centos8-min8 mha4mysql-node-0.58]# yum install perl-CPAN* -y
perl Makefile.PL
make && make install
Can’t locate inc/Module/Install.pm in @INC (you may need to install the inc::Module::Install module)
查看是否安装cpan软件包,已安装后可通过cpan进行perl模块的安装
#yum install perl-CPAN*
[root@centos8-min8 mha4mysql-node-0.58]# cpan inc::Module::Install
> 问题追踪
在centos8.2中执行perl Makefile.PL失败,但在centos7.8中执行成功
7.
安装MHA-Manager管理节点
仅在centos7-min-ha3 192.168.16.23上安装mha-manager管理节点
安装环境需要的介质包 —— (在安装MHA-Node的时候已安装了)
①安装
mha-manager
[root@centos7-min-ha3 ~]# tar -zxf mha4mysql-manager-0.58.tar.gz
[root@centos7-min-ha3 ~]# chown -R root.root mha4mysql-manager-0.58
[root@centos7-min-ha3 ~]# cd mha4mysql-manager-0.58
[root@centos7-min-ha3 mha4mysql-manager-0.58]# perl Makefile.PL
[root@centos7-min-ha3 mha4mysql-manager-0.58]# make && make install
②配置MHA
mkdir /etc/mha
mkdir -p /usr/local/mha
cd /etc/mha/
[root@centos7-min-ha3 scripts]# cat /etc/mha/mha.conf
[root@centos7-min-ha3 scripts]#
cat /usr/local/mha/scripts/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.16.100/24’; # Virtual IP
这里需要根据自己的环境修改
my $key = “1”;
##my $ssh_start_vip = “/sbin/ifcfg ens33:$key $vip”; #注意网卡
##my $ssh_stop_vip = “/sbin/ifcfg ens33:$key down”;
my $ssh_start_vip = “sudo ip addr add $vip dev ens33:$key”;
my $ssh_stop_vip = “sudo ip addr delete $vip dev ens33:$key”;
my $exit_code = 0;
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” ) {
# $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 {
print “\n\n\n***************************************************************\n”;
print “Disabling the VIP – $vip on old master: $orig_master_host\n”;
print “***************************************************************\n\n\n\n”;
&stop_vip();
$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 {
print “\n\n\n***************************************************************\n”;
print “Enabling the VIP – $vip on new master: $new_master_host \n”;
print “***************************************************************\n\n\n\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”;
`ssh $ssh_user\@$orig_master_host \” $ssh_start_vip \”`;
exit 0;
}
else {
&usage();
exit 1;
}
}
# A simple system call that enable the VIP on the new master
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 {
“Usage: master_ip_failover –command=start|stop|stopssh|status –orig_master_host=host –orig_master_ip=ip –orig_master_port=po
rt –new_master_host=host –new_master_ip=ip –new_master_port=port\n”;
}
[root@centos7-min-ha3 scripts]#
cat /usr/local/mha/scripts/master_ip_online_change
#注意VIP
#/bin/bash
source /root/.bash_profile
vip=`echo ‘192.168.16.100/24’` # Virtual IP
key=`echo ‘1’`
command=`echo “$1” | awk -F = ‘{print $2}’`
orig_master_host=`echo “$2” | awk -F = ‘{print $2}’`
new_master_host=`echo “$7” | awk -F = ‘{print $2}’`
orig_master_ssh_user=`echo “${12}” | awk -F = ‘{print $2}’`
new_master_ssh_user=`echo “${13}” | awk -F = ‘{print $2}’`
##stop_vip=`echo “ssh root@$orig_master_host /sbin/ifcfg ens33:$key down”`
##start_vip=`echo “ssh root@$new_master_host /sbin/ifcfg ens33:$key $vip”`
stop_vip=`echo “ssh root@$orig_master_host sudo ip addr delete 192.168.16.100/24 dev ens33:1″`
start_vip=`echo “ssh root@$new_master_host sudo ip addr add 192.168.16.100/24 dev ens33:1″`
if [ $command = ‘stop’ ]
then
echo -e “\n\n\n***************************************************************\n”
echo -e “Disabling the VIP – $vip on old master: $orig_master_host\n”
$stop_vip
if [ $? -eq 0 ]
then
echo “Disabled the VIP successfully”
else
echo “Disabled the VIP failed”
fi
echo -e “***************************************************************\n\n\n\n”
fi
if [ $command = ‘start’ -o $command = ‘status’ ]
then
echo -e “\n\n\n***************************************************************\n”
echo -e “Enabling the VIP – $vip on new master: $new_master_host \n”
$start_vip
if [ $? -eq 0 ]
then
echo “Enabled the VIP successfully”
else
echo “Enabled the VIP failed”
fi
echo -e “***************************************************************\n\n\n\n”
fi
检测所有主机的连通性:
[root@centos7-min-ha3 scripts]#
/usr/local/bin/masterha_check_ssh –conf=/etc/mha/mha.conf
解决方法:
SSH
互信问题,之前是使用
ssh-copy-id
命令,所以在
authorized_keys
中只保存了除本机外的另外两台机器的公钥,需要将三台机器上的本机
ssh
公钥加入
authorized_keys
文件
重试成功
检测复制状态:
[root@centos7-min-ha3 mha]#
/usr/local/bin/masterha_check_repl –conf=/etc/mha/mha.conf
问题解决:启动三台服务器上的mysql服务
[root@centos7-min-ha3 mha]# /root/mysql/support-files/mysql.server start
问题解决:需要重启两台mysql从服务的主从同步复制功能
[root@centos7-min-ha3 mha]# su mysql
[mysql@centos7-min-ha3 mha]$ mysql -uroot -p
Enter password: 123456
mysql> start slave;
8.
在主库上添加VIP
[root@centos7-min-ha1 ~]#
ip addr add 192.168.16.100/24 dev ens33
删除VIP
[root@centos7-min-ha1 ~]# ip addr del 192.168.16.100/24 dev ens33
9.
在管理节点启动MHA服务
启动MHA:
nohup masterha_manager –conf=/etc/mha/mha.conf > /tmp/mha_manager.log < /dev/null 2>&1 &
检测MHA是否启动:
masterha_check_status –conf=/etc/mha/mha.conf
注意:
三、模拟主库故障,故障切换
1.MHA
自动切换主库
MHA
自动切换卡在通过
ssh
漂移
VIP
阶段
主要原因是因为master_ip_failover与master_ip_online_change两个文件配置有问题
[root@centos7-min-ha3 scripts]# find / -name mha.failover.complete
/usr/local/mha/mha.failover.complete
[root@centos7-min-ha3 scripts]# cd /usr/local/mha/
[root@centos7-min-ha3 mha]# rm -rf mha.failover.complete
mha.failover.complete
文件:该文件生成后,将不在允许主库故障后自动切换
删除manager机器上的mha.failover.complete文件后,master机器上就能查看到VIP信息
mha-manager
正常运行,MySQL主从复制正常,模拟主库故障查看VIP从主库21漂移到从库22
将master MySQL服务停止
[root@centos7-min-ha1 ~]# mysql/support-files/mysql.server stop
Shutting down MySQL……….. SUCCESS!
centos7-min-ha1
centos7-min-ha2
VIP漂移之后,centos7-min-ha2从库变成主库,查看centos7-min-ha2 的主从状态
查看centos7-min-ha3 从库的主从状态
> 问题追踪 :
把从库的 Master_Host改成VIP试试
,测试结果为不能解决该问题。这个问题产生的原因是min-ha3与min-ha2的server-id配置成了一样的。
注意:每台MySQL服务器的server-id必须是不一样的
2.
手动切换主库
前提:一主二从状态正常,主库VIP正常,MHA manager启动正常
停止主库服务,VIP切换到从库min-ha2
[root@centos7-min-ha1 ~]# mysql/support-files/mysql.server stop
Shutting down MySQL……….. SUCCESS!
mysql> GRANT ALL PRIVILEGES ON *.* TO ‘root’@’%’ IDENTIFIED BY ‘123456’;
Query OK, 0 rows affected, 1 warning (0.01 sec)
客户端通过VIP访问MySQL服务
数据库主从状态检查
min-ha2 (mater): 自动没有slave
min-ha3: 自动同步切换master到192.168.16.22
min-ha1: 没有slave状态,没有同步新master
后续恢复
① 把min-ha1从库与min-ha2主库进行复制
min-ha1:
② 重启min-ha1 MySQL服务后检查Mha manager服务器并删除
mha.failover.complete
文件
该文件生成后,将不在允许主库故障后自动切换
再重启mha-manager服务
[root@centos7-min-ha3 mha]#
[root@centos7-min-ha3 mha]# nohup masterha_manager –conf=/etc/mha/mha.conf > /tmp/mha_manager.log < /dev/null 2>&1 &
[root@centos7-min-ha3 mha]# masterha_check_status –conf=/etc/mha/mha.confmha (pid:2641) is running(0:PING_OK), master:192.168.16.22
mha.failover.complete存在,min-ha2 (master)故障切换不成功,VIP仍然在min-ha2
再重启min-ha2 MySQL服务,查看主从状态都正常
[root@centos7-min-ha2 ~]# mysql/support-files/mysql.server start
Starting MySQL. SUCCESS!
再测试将/usr/local/mha/mha.failover.complete删除,重启mha服务,再停止MySQL master
[root@centos7-min-ha3 mha]# rm -rf mha.failover.complete
[root@centos7-min-ha3 mha]# nohup masterha_manager –conf=/etc/mha/mha.conf > /tmp/mha_manager.log < /dev/null 2>&1 &
[1] 3127
[root@centos7-min-ha3 mha]# masterha_check_status –conf=/etc/mha/mha.confmha (pid:3127) is running(0:PING_OK), master:192.168.16.22
[root@centos7-min-ha2 ~]# mysql/support-files/mysql.server status
SUCCESS! MySQL running (2720)
[root@centos7-min-ha2 ~]# mysql/support-files/mysql.server stop
Shutting down MySQL………… SUCCESS!
VIP成功再次切换回min-ha1
MySQL
高可用通过,测试完毕。
Min-ha1:
Min-ha2:
Min-ha3:
再将min-ha2以MySQL从机的形式同步min-ha1 MySQL主机