数据库(六)MHA高可用的原理和实际配置
MySQL 作为最流行的开源关系型数据库之一,在企业中广泛应用。为了保证数据库服务的高可用性,避免单点故障,MHA(Master High Availability)提供了一套成熟的 MySQL 高可用解决方案。本文将详细介绍 MHA 的架构、工作原理,并通过实战演示如何搭建一套具备自动故障切换能力的 MySQL 高可用集群。MHA(Master High Availability)是一套优秀的
前言
MySQL 作为最流行的开源关系型数据库之一,在企业中广泛应用。为了保证数据库服务的高可用性,避免单点故障,MHA(Master High Availability)提供了一套成熟的 MySQL 高可用解决方案。本文将详细介绍 MHA 的架构、工作原理,并通过实战演示如何搭建一套具备自动故障切换能力的 MySQL 高可用集群。
一、MHA 概述
1.1 什么是 MHA
MHA(Master High Availability)是一套优秀的 MySQL 高可用环境下故障切换和主从复制的软件,主要用于解决 MySQL 单点故障问题。MHA 能在 0-30 秒内自动完成故障切换操作,并在最大程度上保证数据的一致性,实现真正意义上的高可用。
1.2 MHA 的组成
1.2.1 MHA Node(数据节点)
MHA Node 运行在每台 MySQL 服务器上,负责保存二进制日志、应用差异日志等具体操作。
1.2.2 MHA Manager(管理节点)
MHA Manager 可以单独部署在一台独立机器上,也可以部署在某台 Slave 节点上。其主要功能是定时探测集群中的 Master 节点,并在 Master 故障时自动将最新数据的 Slave 提升为新的 Master,并重新指向其他 Slave。
1.3 MHA 的特点
- 自动故障切换过程中尽可能保存二进制日志,减少数据丢失。
- 支持半同步复制,降低数据丢失风险。
- 支持一主多从架构,最少三台服务器(一主两从)。
- 保证所有节点数据一致性。
1.4 MHA 工作原理
- 从宕机的 Master 保存二进制日志事件(binlog events)。
- 识别含有最新更新的 Slave。
- 应用差异的中继日志(relay log)到其他 Slave。
- 应用从 Master 保存的二进制日志事件。
- 提升一个 Slave 为新的 Master。
- 使其他 Slave 连接新的 Master 进行复制。
1.4.1 从宕机的 Master 保存二进制日志事件 (binlog events)
- 目的:尽可能减少数据丢失
- 实现方式:
- MHA Manager 通过SSH连接到故障Master服务器
- 使用
save_binary_logs
脚本从故障Master上保存尚未复制到Slave的二进制日志 - 如果Master服务器完全无法访问,则使用Slave上的中继日志(relay log)来恢复最新数据
1.4.2 识别含有最新更新的 Slave
- 方法:
- 比较所有Slave的
Exec_Master_Log_Pos
和Relay_Master_Log_File
值 - 通过检查
Seconds_Behind_Master
确定复制延迟最小的Slave - 使用
SHOW SLAVE STATUS
命令获取详细的复制状态信息
- 比较所有Slave的
1.4.3 应用差异的中继日志 (relay log) 到其他 Slave
- 过程:
- 从最新Slave上提取差异的中继日志事件
- 使用
apply_diff_relay_logs
工具将这些差异应用到其他Slave - 确保所有Slave在提升新Master前数据一致
1.4.4 应用从 Master 保存的二进制日志事件
- 操作:
- 将从故障Master保存的二进制日志应用到最新Slave
- 使用
mysqlbinlog
工具解析和应用这些日志 - 确保所有在Master上已提交的事务都被应用到新Master
1.4.5 提升一个 Slave 为新的 Master
- 步骤:
- 在选定的Slave上执行
STOP SLAVE
命令 - 重置复制配置(
RESET MASTER
或RESET SLAVE ALL
) - 修改配置文件(my.cnf)启用log-bin和log-slave-updates
- 如果使用GTID,确保正确设置gtid_executed和gtid_purged
- 在选定的Slave上执行
1.4.6 使其他 Slave 连接新的 Master 进行复制
- 配置:
- 在其他Slave上执行
CHANGE MASTER TO
命令指向新Master - 根据复制方式配置适当的参数(基于binlog位置或GTID)
- 启动Slave线程(
START SLAVE
) - 监控复制状态确保正常运行
- 在其他Slave上执行
1.4.7 其他关键细节
-
故障检测机制:
- MHA Manager定期ping Master服务器
- 可配置超时阈值(默认3次失败判定为故障)
- 支持多种检测方式(网络层、MySQL层、自定义脚本)
-
虚拟IP切换:
- 可选功能,可将虚拟IP从旧Master转移到新Master
- 需要额外配置keepalived或类似工具
-
邮件通知:
- 可配置故障转移前后的邮件通知
- 包含详细的故障信息和操作日志
-
并行复制差异应用:
- MHA可以并行应用差异日志加速故障转移过程
- 通过多线程处理不同数据库的日志
-
数据一致性保证:
- 通过检查
Exec_Master_Log_Pos
确保事务一致性 - 可选启用半同步复制增强数据安全
- 通过检查
-
主库自动隔离:
- 故障转移后可自动将旧Master设置为只读模式
- 防止脑裂情况发生
MHA通过这些精细化的步骤和机制,能够在30秒内完成大多数故障转移场景,最小化停机时间和数据丢失风险。
二、环境准备与搭建
2.1 实验架构
- MHA Manager:192.168.10.120(CentOS 7.9)
- Master:192.168.10.123(CentOS 7.9)
- Slave1:192.168.10.124(CentOS 7.9)
- Slave2:192.168.10.125(CentOS 7.9)
2.2 基础环境配置
2.2.1 关闭防火墙与 SELinux
systemctl stop firewalld
systemctl disable firewalld
setenforce 0
2.2.2 修改主机名
主机名修改完成后,在/etc/hosts加入映射。
hostnamectl set-hostname Master # Master 节点
hostnamectl set-hostname Slave1 # Slave1 节点
hostnamectl set-hostname Slave2 # Slave2 节点
2.3 MySQL 安装与配置
2.3.1 安装 MySQL 5.7
在三台节点上安装 MySQL 5.7,并确保启动成功。
从节点的MySQL版本不能高于主节点,但主节点不能高于
2.3.2 配置 MySQL 主从复制
在从节点配置只读,如果配置文件未配置也可以在数据库行内
Master 节点配置(/etc/my.cnf):
[mysqld]
server-id = 1
log_bin = master-bin
log-slave-updates = true
binlog_format = mixed
expire_logs_days = 7
Slave1 节点配置:
server-id = 2
log_bin = master-bin
relay-log = relay-log-bin
relay-log-index = slave-relay-bin.index
read_only = 1
Slave2 节点配置:
server-id = 3
log_bin = master-bin
relay-log = relay-log-bin
relay-log-index = slave-relay-bin.index
read_only = 1
2.3.2.1 MyCat读写分离与从库read-only的区别对比
MyCat实现的读写分离和直接在MySQL从库上设置read-only
都能实现读写分离的效果,但两者在实现机制和使用场景上有显著区别:
- 实现层面差异
特性 | MyCat读写分离 | 从库read-only设置 |
---|---|---|
实现位置 | 中间件层(应用与数据库之间) | 数据库层(MySQL服务器配置) |
控制粒度 | 可基于SQL语句类型、表、用户等精细控制 | 全局设置,所有连接都只读 |
修改灵活性 | 动态调整,无需重启服务 | 需修改配置并重启从库或会话 |
- 功能特性对比
-
MyCat读写分离优势:
- 智能路由:可基于SQL语句分析自动路由(INSERT/UPDATE/DELETE到主库,SELECT到从库)
- 负载均衡:可在多个从库间实现负载均衡
- 故障转移:自动检测从库状态,故障时自动切换
- 分片支持:可结合分库分表功能使用
- SQL拦截:可拦截危险SQL或实现SQL改写
-
从库read-only特点
- 简单直接:配置简单(
set global read_only=1
) - 强制约束:确保从库不会被意外写入
- 原生支持:无需额外中间件,MySQL原生功能
- 复制安全:确保从库不会产生与主库冲突的写入
- 简单直接:配置简单(
- 典型使用场景
-
适合使用MyCat的场景:
- 需要复杂读写分离策略(如按业务分离)
- 应用无法修改,需要在中间件层实现分流
- 需要结合分库分表功能
- 需要多从库负载均衡
- 需要SQL审计或改写功能
-
适合直接使用read-only的场景:
- 简单的读写分离需求
- 运维人员需要确保从库绝对不被写入
- 资源有限无法部署中间件
- 开发框架已内置读写分离逻辑
- 性能与可靠性考量
- MyCat会增加少量网络开销(额外一跳),但提供更多功能
- read-only是MySQL原生功能,性能零开销
- MyCat单点问题可通过集群解决,read-only无单点问题
如果您的需求只是简单的读写分离,且应用框架能正确处理读写连接,使用MySQL的
read-only
是更简单直接的方案。如果需要更复杂的路由策略、负载均衡或分库分表功能,MyCat等中间件是更好的选择。
2.3.3 创建软链接
ln -s /usr/local/mysql/bin/mysql /usr/sbin/
ln -s /usr/local/mysql/bin/mysqlbinlog /usr/sbin/
2.4 配置一主两从复制
2.4.1 授权同步用户
所有数据库节点的需要授权用户
grant replication slave on *.* to 'myslave'@'192.168.10.%' identified by '123456';
grant all privileges on *.* to 'mha'@'192.168.10.%' identified by '123456'; # manager 使用
grant all privileges on *.* to 'mha'@'master' identified by '123456'; # 防止从库通过主机名连接不上主库
grant all privileges on *.* to 'mha'@'slave1' identified by '123456';
grant all privileges on *.* to 'mha'@'slave2' identified by '123456';
flush privileges;
2.4.2 查看 Master 状态并配置 Slave
查看自己的binlog文件确认自己的起始位置
show master status; -- 记录 File 和 Position
change master to master_host='192.168.10.123', master_user='myslave', master_password='123456', master_log_file='master-bin.000001', master_log_pos=1745;
start slave;
show slave status\G; -- 确认 Slave_IO_Running 和 Slave_SQL_Running 为 Yes
三、MHA 组件安装与配置
3.1 安装 MHA 依赖环境
所有服务器上都安装 MHA 依赖的环境,首先安装 epel 源再装其余依赖
yum install epel-release --nogpgcheck -y
#注意!必须确认依赖完整安装!
yum install -y perl-DBD-MySQL \
perl-Config-Tiny \
perl-Log-Dispatch \
perl-Parallel-ForkManager \
perl-ExtUtils-CBuilder \
perl-ExtUtils-MakeMaker \
perl-CPAN
3.2 安装 MHA Node
在所有节点(包括)上安装 MHA Node:
cd /opt
tar zxvf mha4mysql-node-0.58.tar.gz
cd mha4mysql-node-0.58
perl Makefile.PL
make && make install
3.3 安装 MHA Manager
在 Manager 节点上安装 MHA Manager:
cd /opt
tar zxvf mha4mysql-manager-0.58.tar.gz
cd mha4mysql-manager-0.58
perl Makefile.PL
make && make install
3.3.1 manager与node工具的使用
manager 组件安装后在/usr/local/bin 下面会生成几个工具,主要包括以下几个:
masterha_check_ssh
检查 MHA 的 SSH 配置状况masterha_check_repl
检查 MySQL 复制状况masterha_manger
启动 manager的脚本masterha_check_status
检测当前 MHA 运行状态masterha_master_monitor
检测 master 是否宕机masterha_master_switch
控制故障转移(自动或者 手动)masterha_conf_host
添加或删除配置的 server 信息masterha_stop
关闭manager
node 组件安装后也会在/usr/local/bin 下面会生成几个脚本(这些工具通常由 MHAManager 的脚本触发,无需人为操作)主要如下:
save_binary_logs
保存和复制 master 的二进制日志apply_diff_relay_logs
识别差异的中继日志事件并将其差异的事件应用于其他的 slavefilter_mysqlbinlog
去除不必要的 ROLLBACK 事件(MHA 已不再使用这个工具)purge_relay_logs
清除中继日志(不会阻塞 SQL 线程)
3.4 配置 SSH 无密码认证
在所有节点之间配置 SSH 互信:
ssh-keygen -t rsa
ssh-copy-id 目标IP
在主从数据库节点间以及管理端间建立公私钥,可以进行无密码访问。
3.5 配置 MHA
3.5.1 拷贝脚本
cp -rp /opt/mha4mysql-manager-0.58/samples/scripts /usr/local/bin
cp /usr/local/bin/scripts/master_ip_failover /usr/local/bin
共四个脚本,用来管理主从切换:
master_ip_failover
自动切换时 VIP 管理的脚本master_ip_online_change
在线切换时 vip 的管理power_manager
故障发生后关闭主机的脚本send_report
因故障切换后发送报警的脚本
3.5.2 修改 VIP 脚本(/usr/local/bin/master_ip_failover)
设置 VIP 相关参数:
my $vip = '192.168.10.240'; #指定vip的地址
my $brdc = '192.168.10.255'; #指定vip的广播地址
my $ifdev = 'ens33'; #指定vip绑定的网卡
my $key = '1'; #指定vip绑定的虚拟网卡序列号
my $ssh_start_vip = "/sbin/ifconfig ens33:$key $vip"; #代表此变量值为ifconfig ens33:1 192.168.10.200
my $ssh_stop_vip = "/sbin/ifconfig ens33:$key down"; #代表此变量值为ifconfig ens33:1 192.168.10.200 down
my $exit_code = 0; #指定退出状态码为0
#my $ssh_start_vip = "/usr/sbin/ip addr add $vip/24 brd $brdc dev $ifdev label $ifdev:$key;/usr/sbin/arping -q -A -c 1 -I $ifdev $vip;iptables -F;";
#my $ssh_stop_vip = "/usr/sbin/ip addr del $vip/24 dev $ifdev label $ifdev:$key";
添加vip切换的功能:
sub start_vip() {
`ssh $ssh_user\@$new_master_host \" $ssh_start_vip \"`;
}
sub stop_vip() {
`ssh $ssh_user\@$orig_master_host \" $ssh_stop_vip \"`;
}
3.5.3 创建 MHA 配置文件(/etc/masterha/app1.cnf)
创建管理文件夹
mkdir -p /etc/masterha
cp /opt/mha4mysql-manager-0.58/samples/conf/app1.cnf /etc/masterha
修改app1.cnf的配置
[server default]
manager_log=/var/log/masterha/app1/manager.log
#manager日志
manager_workdir=/var/log/masterha/app1
#manager工作目录
master_binlog_dir=/usr/local/mysql/data
#master保存binlog的位置,这里的路径要与master里配置的binlog的路径一致,以便MHA能找到
master_ip_failover_script=/usr/local/bin/master_ip_failover
#设置自动failover时候的切换脚本,也就是上面的那个脚本
master_ip_online_change_script=/usr/local/bin/master_ip_online_change
#设置手动切换时候的切换脚本
report_script=/usr/local/send_report
#设置发生切换后发送的报警的脚本
shutdown_script=""
#设置故障发生后关闭故障主机脚本(该脚本的主要作用是关闭主机防止发生脑裂,这里没有使用)
secondary_check_script=/usr/local/bin/masterha_secondary_check -s 192.168.10.124 -s 192.168.10.125
#指定检查的从服务器IP地址
ssh_user=root
#设置ssh的登录用户名
user=mha
#设置监控用户root
password=123456
#设置mysql中root用户的密码,这个密码是前文中创建监控用户的那个密码
ping_interval=1
#设置监控主库,发送ping包的时间间隔,默认是3秒,尝试三次没有回应的时候自动进行failover
remote_workdir=/tmp
#设置远端mysql在发生切换时binlog的保存位置
repl_user=myslave
#设置从库用户
repl_password=123456
[server1]
hostname=192.168.10.123
port=3306
[server2]
hostname=192.168.10.124
port=3306
candidate_master=1
#设置为候选master,设置该参数以后,发生主从切换以后将会将此从库提升为主库,即使这个从库不是集群中最新的slave
check_repl_delay=0
#默认情况下如果一个slave落后master 超过100M的relay logs的话,MHA将不会选择该slave作为一个新的master, 因为对于这个slave的恢复需要花费很长时间;通过设置check_repl_delay=0,MHA触发切换在选择一个新的master的时候将会忽略复制延时,这个参数对于设置了candidate_master=1的主机非常有用,因为这个候选主在切换的过程中一定是新的master
[server3]
hostname=192.168.10.125
port=3306
3.6 启动 VIP 并测试 MHA
/sbin/ifconfig ens33:1 192.168.10.240/24 #初次启动
masterha_check_ssh -conf=/etc/masterha/app1.cnf #检查ssh的公私钥登录是否成功,如果正常最后会输出 successfully。
masterha_check_repl -conf=/etc/masterha/app1.cnf #检查mysql主从连接情况,如果正常最后会输出 MySQL Replication Health is OK 。
3.7 启动 MHA
nohup masterha_manager --conf=/etc/masterha/app1.cnf --remove_dead_master_conf --ignore_last_failover < /dev/null > /var/log/masterha/app1/manager.log 2>&1 &
--remove_dead_master_conf
:该参数代表当发生主从切换后,老的主库的 ip 将会从配置文件中移除。--manger_log
:日志存放位置。--ignore_last_failover
:在缺省情况下,如果 MHA 检测到连续发生宕机,且两次宕机间隔不足 8 小时的话,则不会进行 Failover, 之所以这样限制是为了避免 ping-pong 效应。该参数代表忽略上次 MHA 触发切换产生的文件,默认情况下,MHA 发生切换后会在日志记录,也就是上面设置的日志app1.failover.complete文件,下次再次切换的时候如果发现该目录下存在该文件将不允许触发切换,除非在第一次切换后收到删除该文件,为了方便,这里设置为–ignore_last_failover。
正常自动切换一次后,MHA 进程会退出。HMA 会自动修改 app1.cnf 文件内容,将宕机的 master 节点删除,并让slave节点成为了一个新的master节点。
故障切换备选主库的算法:
1.一般判断从库的是从(position/GTID)判断优劣,数据有差异,最接近于master的slave,成为备选主。
2.数据一致的情况下,按照配置文件顺序,选择备选主库。
3.设定有权重(candidate_master=1),按照权重强制指定备选主。
(1)默认情况下如果一个slave落后master 100M的relay logs的话,即使有权重,也会失效。
(2)如果check_repl_delay=0的话,即使落后很多日志,也强制选择其为备选主。
masterha_check_status --conf=/etc/masterha/app1.cnf
查看 MHA 状态,可以看到当前的 master 是 master 节点。
cat /var/log/masterha/app1/manager.log | grep "current master"
查看 MHA 日志,也以看到当前的 master 是 192.168.10.123,如下所示。
masterha_stop --conf=/etc/masterha/app1.cnf
若要关闭 manager 服务,可以使用如上命令。
四、故障模拟与切换
4.1 模拟 Master 宕机
在master上关闭数据库
systemctl stop mysqld
4.2 观察故障切换
tail -f /var/log/masterha/app1/manager.log
ifconfig # 查看 VIP 是否漂移到新 Master
4.3 故障修复与恢复
4.3.1 修复 MySQL 服务
systemctl restart mysqld
4.3.2 重新配置主从
show master status; -- 在新 Master 上查看日志位置
change master to ...; -- 在原 Master 上执行同步
start slave;
4.3.3 修复manager节点的app1.cnf文件
将文件中的secondary_check_script的从库修改为原主库。
secondary_check_script=/usr/local/bin/masterha_secondary_check -s 192.168.10.123 -s 192.168.10.125
并且重新添加被去除的原主库节点,将candidate_master=1、check_repl_delay=0两个参数添加给下一个备选主库。
[server1]
candidate_master=1
check_repl_delay=0
hostname=192.168.10.123
port=3306
[server2]
hostname=192.168.10.124
port=3306
[server3]
hostname=192.168.10.125
port=3306
4.3.4 重启 MHA
修改配置文件后重新启动 MHA:
nohup masterha_manager --conf=/etc/masterha/app1.cnf --remove_dead_master_conf --ignore_last_failover < /dev/null > /var/log/masterha/app1/manager.log 2>&1 &
再测试一下主从复制能否正常:
总结
通过本文的实战演示,我们成功搭建了一套基于 MHA 的 MySQL 高可用集群,并模拟了故障切换过程。MHA 不仅能够快速自动地进行主从切换,还能最大程度保证数据一致性,是企业级 MySQL 高可用方案中的优选之一。
关键要点回顾:
- MHA 架构:由 Manager 和 Node 组成,Manager 负责调度,Node 负责执行具体操作。
- 配置重点:主从复制、SSH 互信、VIP 管理脚本、配置文件编写。
- 故障切换:MHA 会自动选择最优 Slave 提升为 Master,并重新配置其他 Slave。
- 恢复流程:修复原 Master 后需重新加入集群,并重启 MHA 服务。
MHA 虽然配置稍复杂,但其强大的故障切换能力和数据一致性保证,使其成为 MySQL 高可用方案中不可或缺的工具。
更多推荐
所有评论(0)