MySQL MHA高可用
1. 理解 HHA 高可用
[info] MHA 是什么
MHA是mysql高可用解决方案之一。
- 当mysql主库发生故障,MHA提升从库为主库,确保主库高可用。
- MHA能在最大程度上保证数据的一致性,以达到真正意义上的高可用。
[info] 流程图
1.1 设计图拆解分析:
4个长方形代表一共4台服务器, 下面的3台上装MHA_node 和 一主2从(一台master+2台slave), 上面那台服务器则装了MHA _manager, manager 是mha的心跳检测官和总指挥官,node是manager的员工。
1.2 manager干了啥:
- 心跳检测: 检测master是否宕机。
- 一旦宕机,manager会以发送指令给node的方式协调整个主从切换的过程。
虽然我们上面3台mysql,每台都有ip地址, 但是我们应用程序不直接访问这些IP,我们暴露给应用程序的是一个虚拟IP,简称VIP,应用程序通过 VIP访问master。期初,这个VIP(192.168.83.129)是位于我们的master(192.168.168.83.130),后面主机宕机了,VIP漂移到 slave1(192.168.83.131)或者slave2(192.168.83.132)的服务器上。那么应用程序就会写入其中的slave了。
如图所示,这个VIP的切换过程就是通过manager触发IP script脚本完成的。
[info] MHA 由什么组成
-
MHA Manager(管理节点)
建议将MHA Manager单独部署在一台独立的机器上管理多个master-slave集群。 -
MHA Node(数据节点)
MHA Node运行在每台MySQL服务器上,是MHA Manager的员工,接收Manager的命令并执行。
[info] MHA各个工具包的作用
manager工具包:
node工具包:
[info] MHA工作原理
- 从宕机崩溃的master保存二进制日志事件(binlog events)
- 识别含有最新更新的slave
- 应用差异的中继日志(relay log)到其他的slave;
- 应用从master保存的二进制日志事件(binlog events);
- 提升一个slave为新的master;
- 使其他的slave连接新的master进行复制;
2. 搭建 MySQL 一主两从
[info] 建立1主2从
注: 虚拟机镜像复制 需要删除 /www/server/data/auto.cnf
并重启 mysql
2.1. 环境:
MySQL:5.7
192.168.83.130 : 主
192.168.83.131 : 从
192.168.83.132 : 从1
2.2 主节点 master
- 编辑 my.cnf
# vim /etc/my.cnf
vim /www/server/mysql/my.cnf
- 在对应位置添加如下内容:
[mysqld]
server-id=130
log-bin=mysql-bin
binlog-do-db=test
- 重启 mysqld 服务:
service mysqld restart
- 进入mysql 创建用于同步的账号:
# 创建 slave 从服务器连接账号
# grant replication slave on *.* to 'slave'@'192.168.83.%' identified by '123456';
grant all on *.* to 'slave'@'192.168.83.%' identified by '123456';
# 刷新用户权限
flush privileges;
2.3 从节点 slave
- 编辑 my.cnf
vim /www/server/mysql/my.cnf
- 在对应位置添加如下内容:
[mysqld]
server-id=131
log-bin=master-bin
replicate-do-db=test
- 重启 mysqld 服务:
service mysqld restart
- 到 master 查看主节点状态:
show master status \G;
- 执行执行连接主服务器命令:
change master to master_host='192.168.83.130',master_user='slave',master_password='123456',master_log_file='mysql-bin.000009',master_log_pos=908;
- 启动 slave 同步
start slave;
- 查看
show slave status \G;
2.4 从库命令:
停止 slave
stop slave;
重置 slave 配置
reset slave;
3. 建立节点互信
[info] 秘钥互信(节点配置好ssh )
每个节点都执行:
- 安装基础依赖包(每台机器都需要安装)
yum install -y perl-ExtUtils-CBuilder perl-ExtUtils-MakeMaker perl-CPAN perl-DBD-MySQL perl-Config-Tiny perl-Log-Dispatch perl-ParallelForkManager perl-Time-HiRes
- 执行配置命令
cd ~
# 看到提示不用管,一路回车 y 就是
ssh-keygen -t rsa
cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys
只要在一个节点执行即可:(主节点:192.168.83.130)
- 配置
ssh 192.168.83.131 cat ~/.ssh/id_rsa.pub >>~/.ssh/authorized_keys
ssh 192.168.83.132 cat ~/.ssh/id_rsa.pub >>~/.ssh/authorized_keys
# 分发整合后的文件到其它节点
scp ~/.ssh/authorized_keys 192.168.83.131:~/.ssh/
scp ~/.ssh/authorized_keys 192.168.83.132:~/.ssh/
- 在从节点连接主节点测试(是否需要输入密码,不需要则成功)
ip addr | grep 13
ssh root@192.168.83.130
注: 如果测试不行,直接到 从节点 把 密钥 追加过来
ssh 192.168.83.130 cat ~/.ssh/id_rsa.pub >>~/.ssh/authorized_keys
4. 构建 Mha
[info] 构建mha
重要事情说三遍:安装包在评论区!
重要事情说三遍:安装包在评论区!
重要事情说三遍:安装包在评论区!
注: 正式环境 MHA 要安装在一台单独的服务器
注: super_read_only
必须MySQL 5.7 版本以上才有该参数,不然 验证会报错如下:
流程:
- 安装mha node
- 安装mha manger
- 配置mha配置文件
- 检测mha情况
- 演示宕机
4.1. 安装 MHA Node组件
- 登录主节点(192.168.83.130)
mkdir -p /usr/local/mha | cd /usr/local/mha
rz 上传 mha 包
- scp 远程传输 将mha4mysql-node-0.58.tar.gz 到 另外两台子节点
# 无 mha 目录先创建
scp mha4mysql-node-0.58.tar.gz root@192.168.83.131:/usr/local/mha/
scp mha4mysql-node-0.58.tar.gz root@192.168.83.132:/usr/local/mha/
- 解压安装(在所有机器上执行:):
tar -zxvf mha4mysql-node-0.58.tar.gz
cd mha4mysql-node-0.58
perl Makefile.PL
make && make install
- node 安装完成后会得到四个工具,位于
/usr/local/bin/
下面
ll /usr/local/bin/
4.2. 安装 MHA Manager 组件
- 只在主节点 (192.168.83.130) 上安装:
cd /usr/local/mha
tar -zxvf mha4mysql-manager-0.58.tar.gz
perl Makefile.PL
make && make install
- 查看 Manager 工具
ll /usr/local/bin/ | grep master
4.3 配置 MHA Manger
- 创建文件目录
# 创建MHA脚本目录
mkdir /etc/mha/scripts -p
# 创建MHA日志目录
mkdir /var/log/mha/app1 -p
# 创建日志文件
touch /var/log/mha/app1/manager.log
- MHA 应用配置文件
vim /etc/mha/app1.cnf
candidate_master=1的意思是是否能提升为master
[server default]
manager_workdir=/var/log/mha/app1
manager_log=/var/log/mha/app1/manager.log
[server1]
hostname=192.168.83.130
port=3306
[server2]
hostname=192.168.83.131
port=3306
candidate_master=1
[server3]
hostname=192.168.83.132
port=3306
- MHA 检测配置文件
vim /etc/masterha_default.cnf
只需要改用户名 密码、master_binlog_dir、secondary_check_script:
[server default]
user=slave
password=123456
repl_user=slave
repl_password=123456
ssh_user=root
ping_interval=1
master_binlog_dir=/www/server/data
manager_workdir=/var/log/mha/app1
manager_log=/var/log/mha/app1/manager.log
master_ip_failover_script="/etc/mha/scripts/master_ip_failover"
master_ip_online_change_script="/etc/mha/scripts/master_ip_online_change"
report_script="/etc/mha/scripts/send_report"
remote_workdir=/tmp
secondary_check_script= /usr/local/bin/masterha_secondary_check -s 192.168.83.130 -s 192.168.83.131 -s 192.168.83.132
shutdown_script=""
MHA主要配置文件说明:
manager_workdir=/var/log/masterha/app1:设置manager的工作目录
manager_log=/var/log/masterha/app1/manager.log:设置manager的日志文件
master_binlog_dir=/opt/mysql_data:设置master 保存binlog的位置,以便MHA可以找到master的日志
master_ip_failover_script="/etc/mha/scripts/master_ip_failover":设置自动failover时候的切换脚本
master_ip_online_change_script="/etc/mha/scripts/master_ip_online_change":设置手动切换时候的切换脚本
user=root:设置监控mysql的用户
password=dayi123:设置监控mysql的用户,需要授权能够在manager节点远程登录
ping_interval=1:设置监控主库,发送ping包的时间间隔,默认是3秒,尝试三次没有回应的时候自动进行railover
remote_workdir=/tmp:设置远端mysql在发生切换时binlog的保存位置
repl_user=repl :设置mysql中用于复制的用户密码
repl_password=replication:设置mysql中用于复制的用户
report_script=/usr/local/send_report:设置发生切换后发送的报警的脚本
shutdown_script="":设置故障发生后关闭故障主机脚本(该脚本的主要作用是关闭主机放在发生脑裂,这里没有使用)
ssh_user=root //设置ssh的登录用户名
candidate_master=1:在节点下设置,设置当前节点为候选的master
slave check_repl_delay=0 :在节点配置下设置,默认情况下如果一个slave落后master 100M的relay logs的话,MHA将不会选择该slave作为一个新的master;这个选项对于对于设置了candidate_master=1的主机非常有用
- 脚本配置
vim /etc/mha/scripts/master_ip_failover
注意把下文中的变量
v
i
p
和
vip和
vip和key 换成自己的。另外,如果网卡类型不是ens33的,就要把文中的ens33缓存自己的,因为老师的是ens33,所以写的是ens33:
注: 最好不要 copy 代码,直接从 master_ip_failover
文件中 修改 copy
#!/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.83.10';
my $key = '0';
my $ssh_start_vip = "ifconfig ens33:0 192.168.83.10 netmask 255.255.255.0 up";
my $ssh_stop_vip = "/sbin/ifconfig ens33:$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,
'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 {
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";
}
添加执行权限:
chmod +x /etc/mha/scripts/master_ip_failover
-
验证 MHA 相关操作
5.1 通过 masterha_check_ssh 命令验证ssh 信任登录是否成功
masterha_check_ssh --conf=/etc/mha/app1.cnf
如报错: 直接更新 yum 再次安装 如下包
yum -y update yum install -y perl-ParallelForkManager
5.2 通过 masterha_check_repl 命令验证 mysql 主从复制是否成功
masterha_check_repl --conf=/etc/mha/app1.cnf
提示: MySQL Replication Health is OK 表示成功
如报错: mha服务器连接不上83.130 这台服务器节点
# 在3台服务器 添加权限(正式环境 all 谨慎) grant all on *.* to 'slave'@'192.168.83.%' identified by '123456'; # 刷新用户权限 flush privileges;
如报错: All log-bin enabled servers must have same binlog filtering rules (same
# 我在主上开了复制过滤,在从上也必须开启(3台服务器复制过滤要一样) log-bin=mysql-bin binlog-do-db=test replicate-do-db=test
如报错: Slaves settings check failed!
如报错: 检查 mysqlbinlog 设置软链接 (3台都需要设置)
# which mysqlbinlog:查看当前软链接地址 ln -s /www/server/mysql/bin/mysqlbinlog /usr/local/bin/mysqlbinlog # which mysql:查看当前软链接地址 ln -s /www/server/mysql/bin/mysql /usr/local/bin/mysql # 如还不行:再配置(/usr/bin /usr/local/sbin export)再重启3台服务器 ln -s /www/server/mysql/bin/mysqlbinlog /usr/bin/mysqlbinlog # ln -s /www/server/mysql/bin/mysqlbinlog /usr/bin/mysqlbinlog | ln -s /www/server/mysql/bin/mysql /usr/bin/mysql # rm -rf /usr/local/bin/mysqlbinlog | rm -rf /usr/bin/mysqlbinlog | rm -rf /usr/local/sbin/mysqlbinlog | rm -rf /usr/local/bin/mysql | rm -rf /usr/bin/mysql | rm -rf /usr/local/sbin/mysql
如报错: 设置 最高权限
chmod -R 777 /etc/mha/scripts/master_ip_failover
如报错: 不稳定,时不时出现(重启主服务器 或 2台从服务器)(关闭防火墙 firewalld)
5. 启动并测试 MHA
[info] 启动并测试MHA
初次使用的时候,需要先在master上添加vip,以后就不需要了。
# 网卡 和 IP 换成自己的
ifconfig ens33:0 192.168.83.10 netmask 255.255.255.0 up
ip addr | grep 83.10
- 启动manager, 这一步在manager上操作:
# 前台启动:masterha_manager --conf=/etc/mha/app1.cnf --remove_dead_master_conf --ignore_last_failover < /dev/null > /var/log/mha/app1/manager.log
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 &
- 再打开一个 master (192.168.83.130)节点,直接关闭 mysql 服务
service mysqld stop
master (192.168.83.130)节点已经停止并自动故障转移:
- 登录 192.168.83.132 从节点查看是否 切换到 指定的 192.168.83.131
mysql -uroot -p123456
show slave status \G;
- 登录 192.168.83.131 查看ip是否变成vip
ip addr | grep 83.10
6. 修复宕机的 Master 并转为 Slave
[info] 修复宕机的 master 和 日常维护命令
- 修复宕机的 master:
通常情况下自动切换以后,原master可能已经废弃掉,待原master主机修复后,如果数据完整的情况下,可能想把原来master重新作为新主库的slave,这时我们可以借助当时自动切换时刻的MHA日志来完成对原master的修复。下面是提取相关日志的命令:
# 查看日志内容
cat /var/log/mha/app1/manager.log
All other slaves should start replication from here. Statement should be: CHANGE MASTER TO MASTER_HOST='192.168.83.131', MASTER_PORT=3306, MASTER_LOG_FILE='mysql-bin.000006', MASTER_LOG_POS=1769, MASTER_USER='slave', MASTER_PASSWORD='xxx';
意思是说,如果Master主机修复好了,可以在修复好后的Master执行 change master
操作,作为新的slave库。
- 日常维护命令:
# SSH检查
masterha_check_ssh --conf=/etc/mha/app1.cnf
# 主从检查
masterha_check_repl --conf=/etc/mha/app1.cnf
# 停止MHA
masterha_stop --conf=/etc/mha/app1.cnf
# 检查状态
masterha_check_status --conf=/etc/mha /app1.cnf
# 查看 master 日志
tail -f /var/log/mha/app1/manager.log
# 当有slave 节点宕掉时,默认是启动不了的,加上 --ignore_fail_on_start 即使有节点宕掉也能启动MHA,如下:
nohup masterha_manager --conf=/etc/masterha/app1.cnf --ignore_fail_on_start &>/tmp/mha_manager.log &
-
示例: 当前 master(192.168.83.130)已停止服务
3.1 登录 master 启动 mysql 服务service mysqld start
3.2 根据 master 日志 manager.log 重新开始
change master
change master to master_host='192.168.83.131',master_user='slave',master_password='123456',master_log_file='mysql-bin.000006',master_log_pos=1769; start slave; show slave status \G;
3.3 再 新 master (192.168.83.131)插入数据查看效果
192.168.83.131:(主)
192.168.83.132:(从1)
192.168.83.130:(从2,旧 master)