MySQL高可用之MHA


MHA简介

MHA(Master High Availability)是一套针对MySQL的高可用解决方案,能实现自动故障检测与主从切换,有效减少MySQL故障恢复时间,提高服务可用性。

image-20250815153327732

其核心特点包括:

  1. 自动故障检测与切换:通过定期监控主库状态,当主库出现故障(如宕机、网络中断等)时,能自动识别并在从库中选择最合适的节点提升为新主库,整个过程无需人工干预。

  2. 数据一致性保障:在切换过程中,会尽量复制主库未同步到从库的binlog日志,最大程度减少数据丢失;支持GTID(全局事务标识),简化binlog定位与同步流程。

  3. 灵活的候选主库选择:可通过配置指定优先成为新主库的候选节点,优先选择数据最新、负载较低的从库,确保切换后服务稳定。

  4. 低性能损耗:监控过程对MySQL集群性能影响极小,仅通过SSH和MySQL账号进行轻量通信。

  5. 架构简洁:由Manager(管理节点)和Node(数据节点代理)两部分组成,Manager负责监控和决策,Node部署在所有MySQL节点上执行具体操作(如复制管理、binlog处理等)。

MHA适用于一主多从的MySQL架构,广泛应用于需要高可用保障的生产环境,尤其适合对数据库 downtime 敏感的业务场景。不过需要注意的是,它本身不提供负载均衡功能,通常需与其他工具(如ProxySQL、HAProxy)配合使用以实现读写分离和流量切换。

MHA实战

要搭建MHA,要求一个复制集群中必须最少有三台数据库服务器,一主二从,即一台master,一台充当备用master,另外一台充当从库。

MHA Manager会定时探测集群中的master节点,当master出现故障时,它可以自动将最新数据的slave提升为新的master,然后将所有其他的slave重新指向新的master,整个故障转移过程对应用程序完全透明。

一、环境准备

1. 服务器规划(至少3节点)

角色 主机名 IP地址 说明
Master mha-node1 192.168.8.11 主库
Slave1 mha-node2 192.168.8.12 从库(候选主库)
Slave2 mha-node3 192.168.8.13 从库
Manager mha-manager 192.168.8.14 MHA管理节点(独立服务器)

2. 基础配置(所有节点)

# 关闭防火墙
systemctl stop firewalld && systemctl disable firewalld

# 关闭SELinux
setenforce 0
sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config

# 配置hosts(所有节点一致)
cat >> /etc/hosts << EOF
192.168.8.11 mha-node1
192.168.8.12 mha-node2
192.168.8.13 mha-node3
192.168.8.14 mha-manager
EOF

# 配置SSH免密登录(manager节点需免密登录所有数据库节点,数据库节点间也需互信)
ssh-keygen -t rsa -N '' -f ~/.ssh/id_rsa
for host in mha-node1 mha-node2 mha-node3; do
  ssh-copy-id -i ~/.ssh/id_rsa.pub $host
done

二、部署MySQL 8.0主从复制

1. 安装MySQL 8.0(所有数据库节点)

# 这里使用MySQL安装脚本
wget  http://192.168.56.200/Software/mysql_install.sh
bash mysql_install.sh

2. 配置MySQL(主从差异化配置)

Master(mha-node1)配置
vim  /etc/my.cnf
[mysqld]
# ...
# 在默认配置下方添加:
server-id=11  # 唯一ID
log_bin=mysql-bin  # 开启binlog
binlog_format=ROW  # ROW模式(MHA推荐)
gtid_mode=ON  # 开启GTID
enforce_gtid_consistency=ON  # 强制GTID一致性
log_slave_updates=ON  # 从库同步时记录binlog(用于级联复制)
skip_name_resolve=ON  # 跳过域名解析

systemctl restart mysqld
Slave(mha-node2/mha-node3)配置
# mha-node2(server-id=12)
vim  /etc/my.cnf
[mysqld]
# ...
server-id=12  # 唯一ID(mha-node3设为13)
log_bin=mysql-bin
binlog_format=ROW
gtid_mode=ON
enforce_gtid_consistency=ON
log_slave_updates=ON
skip_name_resolve=ON
relay_log=relay-bin  # 开启中继日志
read_only=ON  # 从库只读(可选)

systemctl restart mysqld

3. 搭建主从复制(基于GTID)

在Master(mha-node1)创建复制用户
-- MySQL 8.0默认认证插件为caching_sha2_password,MHA需用mysql_native_password
CREATE USER 'repl'@'192.168.8.%' IDENTIFIED WITH mysql_native_password BY 'Repl@123';
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'192.168.8.%';
FLUSH PRIVILEGES;
在Slave(mha-node2/mha-node3)配置复制
-- 登录Slave的MySQL
CHANGE MASTER TO
  MASTER_HOST='mha-node1',
  MASTER_USER='repl',
  MASTER_PASSWORD='Repl@123',
  MASTER_PORT=3306,
  MASTER_AUTO_POSITION=1;  # 基于GTID自动定位

-- 启动复制
START SLAVE;

-- 检查复制状态(确保Slave_IO_Running和Slave_SQL_Running均为Yes)
SHOW SLAVE STATUS\G;

三、部署MHA

1. 安装依赖(所有节点)

# 安装Perl依赖(MHA基于Perl开发)
# CentOS7安装依赖
yum install -y perl-DBD-MySQL perl-Config-Tiny perl-Log-Dispatch perl-Parallel-ForkManager perl-ExtUtils-CBuilder perl-ExtUtils-MakeMaker

# Ubuntu22.04安装依赖包
sudo apt install -y perl libdbi-perl libdbd-mysql-perl libperl-dev libconfig-tiny-perl liblog-dispatch-perl libparallel-forkmanager-perl

2. 安装MHA包

下载MHA源码包(所有节点)
# wget https://github.com/yoshinorim/mha4mysql-manager/releases/download/v0.58/mha4mysql-manager-0.58.tar.gz
# wget https://github.com/yoshinorim/mha4mysql-node/releases/download/v0.58/mha4mysql-node-0.58.tar.gz

# 局域网下载
wget http://192.168.56.200/Software/mha4mysql-manager-0.58.tar.gz
wget http://192.168.56.200/Software/mha4mysql-node-0.58.tar.gz
安装MHA Node(所有数据库节点)
tar -zxvf mha4mysql-node-0.58.tar.gz
cd mha4mysql-node-0.58
perl Makefile.PL
make && make install
安装MHA Manager(仅manager节点)
tar -zxvf mha4mysql-manager-0.58.tar.gz
cd mha4mysql-manager-0.58
perl Makefile.PL
make && make install

# 创建MHA工作目录
mkdir -p /etc/mha/mha_cluster /var/log/mha/mha_cluster

3. 配置MHA

创建MHA配置文件(manager节点)
cat > /etc/mha/mha_cluster.cnf << EOF
[server default]
# MHA管理用户(需在所有MySQL节点创建)
user=mha_user
password=Mha@123
ssh_user=root  # SSH登录用户
repl_user=repl  # 复制用户
repl_password=Repl@123
ping_interval=1  # 健康检查间隔(秒)
master_binlog_dir=/var/lib/mysql  # master的binlog目录
remote_workdir=/tmp  # 远程节点临时目录
secondary_check_script=masterha_secondary_check -s mha-node2 -s mha-node3  # 二次检查节点
manager_workdir=/var/log/mha/mha_cluster  # manager工作目录
manager_log=/var/log/mha/mha_cluster/manager.log  # manager日志

[server1]
hostname=mha-node1
port=3306
candidate_master=0  # 不优先作为候选主库

[server2]
hostname=mha-node2
port=3306
candidate_master=1  # 优先作为候选主库(数据最新时)
check_repl_delay=0  # 忽略复制延迟,强制作为候选

[server3]
hostname=mha-node3
port=3306
candidate_master=0
EOF
创建MHA管理用户(所有MySQL节点)
CREATE USER 'mha_user'@'192.168.8.%' IDENTIFIED WITH mysql_native_password BY 'Mha@123';
GRANT ALL PRIVILEGES ON *.* TO 'mha_user'@'192.168.8.%';
FLUSH PRIVILEGES;

四、验证MHA配置

1. 检查SSH连接(manager节点)

masterha_check_ssh --conf=/etc/mha/mha_cluster.cnf
# 输出"All SSH connection tests passed successfully."即为正常

2. 检查主从复制(manager节点)

masterha_check_repl --conf=/etc/mha/mha_cluster.cnf
# 输出"MySQL Replication Health is OK."即为正常

五、启动MHA Manager

# 前台启动(测试用,日志实时输出)
masterha_manager --conf=/etc/mha/mha_cluster.cnf

# 后台启动(生产用)
nohup masterha_manager --conf=/etc/mha/mha_cluster.cnf > /var/log/mha/mha_cluster/nohup.log 2>&1 &

# 检查MHA状态
masterha_check_status --conf=/etc/mha/mha_cluster.cnf
# 输出"mha_cluster (pid: xxxx) is running(0:PING_OK)"即为正常运行

六、测试故障切换

1. 模拟Master故障(在mha-node1执行)

systemctl stop mysqld  # 停止主库服务

2. 观察故障切换(manager节点日志)

tail -f /var/log/mha/mha_cluster/manager.log
# 正常情况下,日志会显示:
# - 检测到master故障
# - 提升mha-node2为新master
# - 其他slave(mha-node3)指向新master

3. 验证切换结果

# 在新master(mha-node2)查看状态
mysql -uroot -p -e "SELECT @@server_id, @@read_only;"
# 应显示server_id=12,read_only=OFF

# 在mha-node3查看复制状态
mysql -uroot -p -e "SHOW SLAVE STATUS\G"
# 应显示Master_Host为mha-node2,且复制正常

七、故障恢复后处理

  1. 修复原master(mha-node1),重新安装MySQL并配置为新master(mha-node2)的从库。
  2. 重新启动MHA Manager(故障切换后Manager会自动退出):
nohup masterha_manager --conf=/etc/mha/mha_cluster.cnf > /var/log/mha/mha_cluster/nohup.log 2>&1 &

注意事项

  1. MySQL 8.0兼容性:需使用MHA 0.58版本,且用户认证插件必须为mysql_native_password
  2. GTID依赖:建议开启GTID,减少MHA切换时的binlog定位复杂度。
  3. 候选主库选择candidate_master=1的节点应尽量与原master数据一致(复制延迟小)。
  4. 日志监控:定期检查MHA日志,及时发现潜在问题(如SSH连接失败、复制延迟等)。

通过以上步骤,即可完成MySQL 8.0环境下的MHA高可用部署,实现主库故障时的自动切换,提升数据库服务可用性。