在MySQL高可用部署方案中,MHA(Master High Availability)是常用的主从切换工具,但原生MHA的故障检测依赖脚本轮询,感知速度较慢且切换后需要手动更新应用侧的连接配置。结合consul的服务发现与健康检查机制,可以实现故障的实时感知与切换后服务地址的自动更新,让应用无需修改配置即可访问新的主库。

核心组件与原理
整个方案涉及三个核心组件,各自的作用如下:
- consul集群:提供服务注册、健康检查、服务发现能力,所有MySQL实例启动后向consul注册自身信息,consul持续对实例进行健康探测。
- MHA Manager:负责监控主库状态,当主库故障时触发切换逻辑,选取出新的主库并完成主从关系重构。
- consul-template:监听consul中MySQL主库的服务信息变化,当主库切换后自动更新本地配置文件或触发应用侧的连接配置更新。
整体流程为:主库故障后consul第一时间检测到健康状态异常,标记该实例不可用;MHA Manager感知到主库不可用后执行自动切换,将其中一个从库提升为新主库;新主库向consul更新注册信息,consul-template监听到变化后更新应用侧的连接配置,完成整个自动切换流程。
环境准备
假设我们有3台服务器,角色分配如下:
| 服务器IP | 部署角色 |
|---|---|
| 192.168.0.10 | consul server节点、MHA Manager、consul-template |
| 192.168.0.11 | MySQL主库、consul client节点 |
| 192.168.0.12 | MySQL从库、consul client节点 |
首先完成基础环境配置:所有服务器安装consul,192.168.0.11和192.168.0.12部署MySQL主从复制,192.168.0.10部署MHA Manager并配置好SSH免密登录到两台MySQL服务器。
consul服务注册配置
在192.168.0.11和192.168.0.12上,配置consul client的注册文件,让MySQL实例启动后自动向consul注册。以下是192.168.0.11的注册配置示例:
{
"service": {
"name": "mysql-master",
"tags": ["master"],
"port": 3306,
"check": {
"tcp": "192.168.0.11:3306",
"interval": "5s",
"timeout": "3s"
}
}
}
192.168.0.12的从库注册配置将name改为mysql-slave,tags改为slave,check的tcp地址改为192.168.0.12:3306即可。启动consul client时指定该配置文件,MySQL实例正常运行后,consul就会将其纳入健康监控范围。
MHA自动切换配置
MHA的核心配置文件需要指定所有MySQL节点的信息,以及切换后需要执行的脚本。以下是MHA的配置文件示例:
[server default] manager_workdir=/var/log/mha/app1 manager_log=/var/log/mha/app1/manager.log ssh_user=root repl_user=repl repl_password=repl_pass master_binlog_dir=/var/lib/mysql remote_workdir=/tmp [server1] hostname=192.168.0.11 port=3306 master_binlog_dir=/var/lib/mysql [server2] hostname=192.168.0.12 port=3306 candidate_master=1
为了实现切换后自动更新consul中的主库信息,需要配置MHA的切换后脚本。在MHA配置中添加如下参数:
master_ip_failover_script=/usr/local/bin/mha_failover.sh
切换脚本的核心逻辑是:当新主库提升完成后,向consul发送请求,更新mysql-master服务的注册信息为新主库的IP和端口,同时注销旧主库的注册信息。脚本示例如下:
#!/bin/bash
# 新主库IP
new_master_ip=$6
# 旧主库IP
old_master_ip=$7
# 注销旧主库的服务注册
curl -X PUT "http://192.168.0.10:8500/v1/agent/service/deregister/mysql-master" > /dev/null 2>&1
# 向consul注册新主库
curl -X PUT "http://192.168.0.10:8500/v1/agent/service/register" -d '{
"Name": "mysql-master",
"Port": 3306,
"Address": "'"$new_master_ip"'",
"Check": {
"TCP": "'"$new_master_ip"':3306",
"Interval": "5s",
"Timeout": "3s"
}
}' > /dev/null 2>&1
exit 0
consul-template配置
应用侧通过consul-template动态获取mysql-master的服务地址,当主库切换后,consul-template监听到服务信息变化,自动更新应用配置文件。首先创建模板文件mysql.tmpl:
{{range service "mysql-master"}}
mysql.host={{.Address}}
mysql.port={{.Port}}
{{end}}
启动consul-template,指定模板文件和输出路径,同时配置当模板渲染结果变化后自动重载应用:
consul-template -template "mysql.tmpl:/etc/app/mysql.properties:systemctl reload app-service" -consul-addr 192.168.0.10:8500
完整切换流程验证
手动停止192.168.0.11的MySQL服务,模拟主库故障:
systemctl stop mysqld
此时可以观察到以下现象:
- consul的健康检查在5秒内检测到192.168.0.11的3306端口不通,标记mysql-master服务不可用。
- MHA Manager在检测到主库故障后,自动执行切换逻辑,将192.168.0.12提升为新主库,完成主从关系重构。
- MHA的切换脚本向consul更新mysql-master的注册信息为192.168.0.12:3306。
- consul-template监听到服务信息变化,重新渲染模板,更新/etc/app/mysql.properties文件,并自动重载应用服务。
- 应用无需修改任何配置,通过新的配置文件连接到192.168.0.12的新主库,服务无感知恢复。
注意事项
在实际部署中需要注意以下几点:
- consul集群建议部署3个以上server节点,避免单点故障导致服务发现失效。
- MHA的切换脚本需要做好幂等处理,避免重复切换时执行重复操作。
- 健康检查的频率不要设置过低,避免对MySQL实例造成不必要的压力,建议间隔设置为5-10秒。
- 所有组件的日志需要统一收集,方便切换异常时排查问题。