MHA 高可用脚本与故障切换策略:深度解析
大家好!今天我们来深入探讨 MHA (Master High Availability) 的高可用脚本与故障切换策略。MHA 是一套优秀的 MySQL 高可用解决方案,它能在主库发生故障时,自动将其中一个 Slave 提升为新的 Master,从而保障数据库服务的持续可用性。
今天的内容将涵盖 MHA 的核心组件、工作原理,以及如何编写和配置自定义脚本来实现更精细化的故障切换控制。
1. MHA 的核心组件与工作原理
MHA 主要由两个核心组件构成:
-
MHA Manager (管理节点): 负责监控 MySQL 集群的状态,检测 Master 节点是否发生故障,并在故障发生时执行故障切换。
-
MHA Node (数据节点): 部署在 MySQL 服务器上,负责执行 Manager 发出的指令,例如启动、停止 MySQL 服务,执行数据恢复等操作。
工作原理:
- 监控: MHA Manager 定期通过 SSH 连接到 MySQL 服务器,执行
SHOW SLAVE STATUS
、SHOW MASTER STATUS
等命令,检查 Master 是否正常运行,以及 Slave 的复制状态。 - 故障检测: 如果 Manager 在预定时间内无法连接到 Master,或者检测到 Master 的复制状态异常,则判定 Master 发生故障。
- 故障切换: Manager 会根据预先设定的策略,选择一个合适的 Slave 作为新的 Master。
- 数据恢复: Manager 会将新的 Master 的二进制日志位置同步到其他 Slave,确保所有 Slave 都能从新的 Master 继续复制数据。
- 客户端重定向: Manager 会更新客户端的连接配置,将客户端重定向到新的 Master。
2. MHA 的故障切换策略
MHA 提供了多种故障切换策略,可以根据不同的业务需求进行选择。常见的策略包括:
-
最先进策略 (Most Up-to-Date Slave): 选择复制延迟最小的 Slave 作为新的 Master,保证数据一致性最高。
-
指定优先级策略 (Preferred Slave): 可以为 Slave 设置优先级,MHA 会优先选择优先级最高的 Slave 作为新的 Master。
-
手动切换策略 (Manual Failover): 手动指定新的 Master,适用于需要人工干预的场景。
MHA 默认使用最先进策略,但在实际应用中,可以通过配置 preferred_master_candidate
和 no_master_candidate
等参数,来调整 Slave 的选择优先级。
3. 自定义 MHA 脚本:扩展故障切换能力
MHA 允许用户自定义脚本,在故障切换的不同阶段执行特定的操作。这为我们提供了极大的灵活性,可以根据业务需求定制故障切换流程。
MHA 支持以下几种类型的自定义脚本:
master_ip_online_change
: 在新的 Master 上线时执行。master_ip_offline_change
: 在旧的 Master 下线时执行。secondary_check_script
: 在故障检测阶段执行,用于更精确地判断 Master 是否发生故障。pre_switchover_script
: 在故障切换开始前执行。post_switchover_script
: 在故障切换完成后执行。pre_online_change_script
: 在新的 Master 上线前执行。post_online_change_script
: 在新的 Master 上线后执行。pre_offline_change_script
: 在旧的 Master 下线前执行。post_offline_change_script
: 在旧的 Master 下线后执行。
3.1 脚本参数
MHA 在执行自定义脚本时,会传递一些参数,这些参数包含了集群的信息、新旧 Master 的信息等。常见的参数包括:
--manager
: MHA Manager 的主机名或 IP 地址。--appname
: 应用名称。--new_master_host
: 新的 Master 的主机名。--new_master_ip
: 新的 Master 的 IP 地址。--new_master_port
: 新的 Master 的端口号。--orig_master_host
: 旧的 Master 的主机名。--orig_master_ip
: 旧的 Master 的 IP 地址。--orig_master_port
: 旧的 Master 的端口号。--candidate_master_host
: 候选 Master 的主机名。--candidate_master_ip
: 候选 Master 的 IP 地址。--candidate_master_port
: 候选 Master 的端口号。
3.2 脚本示例
下面我们来看几个自定义脚本的示例,演示如何利用这些脚本来扩展 MHA 的故障切换能力。
示例 1: master_ip_online_change
脚本:更新 DNS 记录
这个脚本的作用是在新的 Master 上线时,自动更新 DNS 记录,将域名指向新的 Master 的 IP 地址。
#!/bin/bash
# 获取参数
NEW_MASTER_IP=$1
APP_NAME=$2
# 更新 DNS 记录
# 这里需要根据你的 DNS 服务商提供的 API 进行修改
# 假设使用 Cloudflare API
ZONE_ID="your_zone_id"
RECORD_ID="your_record_id"
API_TOKEN="your_api_token"
curl -s -X PUT "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/dns_records/${RECORD_ID}"
-H "Authorization: Bearer ${API_TOKEN}"
-H "Content-Type: application/json"
--data "{"type":"A","name":"mysql.example.com","content":"${NEW_MASTER_IP}","ttl":120,"proxied":false}"
if [ $? -eq 0 ]; then
echo "DNS record updated successfully to ${NEW_MASTER_IP}"
else
echo "Failed to update DNS record"
exit 1
fi
exit 0
配置方法:
在 MHA 的配置文件中,添加以下配置:
master_ip_online_change=/path/to/master_ip_online_change.sh
示例 2: secondary_check_script
脚本:自定义健康检查
这个脚本的作用是在故障检测阶段,执行自定义的健康检查,例如检查 MySQL 的连接数、QPS 等指标,更精确地判断 Master 是否发生故障。
#!/bin/bash
# 获取参数
MASTER_HOST=$1
MASTER_PORT=$2
# 执行健康检查
# 这里需要根据你的业务需求进行修改
MYSQL_CONN=$(mysql -h ${MASTER_HOST} -P ${MASTER_PORT} -u root -e "show status like 'Threads_connected';" | awk '/Threads_connected/ {print $2}')
MYSQL_QPS=$(mysql -h ${MASTER_HOST} -P ${MASTER_PORT} -u root -e "show status like 'Questions';" | awk '/Questions/ {print $2}')
if [ -z "${MYSQL_CONN}" ] || [ -z "${MYSQL_QPS}" ]; then
echo "Failed to get MySQL status"
exit 1
fi
if [ ${MYSQL_CONN} -gt 1000 ] || [ ${MYSQL_QPS} -gt 10000 ]; then
echo "MySQL is overloaded"
exit 1
fi
# 如果健康检查通过,则返回 0
exit 0
配置方法:
在 MHA 的配置文件中,添加以下配置:
secondary_check_script=/path/to/secondary_check_script.sh
示例 3: pre_switchover_script
脚本:锁定应用程序
这个脚本的作用是在故障切换开始前,锁定应用程序,防止在切换过程中产生新的数据写入。
#!/bin/bash
# 获取参数
APP_NAME=$1
# 锁定应用程序
# 这里需要根据你的应用程序的特点进行修改
# 假设使用 Nginx 作为反向代理,可以通过修改 Nginx 配置来实现锁定
NGINX_CONFIG="/etc/nginx/nginx.conf"
# 备份 Nginx 配置文件
cp ${NGINX_CONFIG} ${NGINX_CONFIG}.bak
# 修改 Nginx 配置文件,返回 503 错误
sed -i "s/proxy_pass http://backend;/return 503;/" ${NGINX_CONFIG}
# 重启 Nginx
systemctl reload nginx
if [ $? -eq 0 ]; then
echo "Application locked successfully"
else
echo "Failed to lock application"
exit 1
fi
exit 0
配置方法:
在 MHA 的配置文件中,添加以下配置:
pre_switchover_script=/path/to/pre_switchover_script.sh
示例 4: post_switchover_script
脚本:解锁应用程序
这个脚本的作用是在故障切换完成后,解锁应用程序,允许新的数据写入。
#!/bin/bash
# 获取参数
APP_NAME=$1
# 解锁应用程序
# 这里需要根据你的应用程序的特点进行修改
# 假设使用 Nginx 作为反向代理,可以通过恢复 Nginx 配置来实现解锁
NGINX_CONFIG="/etc/nginx/nginx.conf"
# 恢复 Nginx 配置文件
mv ${NGINX_CONFIG}.bak ${NGINX_CONFIG}
# 重启 Nginx
systemctl reload nginx
if [ $? -eq 0 ]; then
echo "Application unlocked successfully"
else
echo "Failed to unlock application"
exit 1
fi
exit 0
配置方法:
在 MHA 的配置文件中,添加以下配置:
post_switchover_script=/path/to/post_switchover_script.sh
4. MHA 配置文件详解
MHA 的配置文件主要有两个:
manager.cnf
: MHA Manager 的配置文件,用于配置集群信息、监控策略、故障切换策略等。node.cnf
: MHA Node 的配置文件,用于配置 MySQL 服务器的信息、SSH 连接信息等。
4.1 manager.cnf
常用配置项
配置项 | 说明 |
---|---|
appname |
应用名称,用于区分不同的 MHA 集群。 |
user |
连接 MySQL 服务器的用户名。 |
password |
连接 MySQL 服务器的密码。 |
ssh_user |
SSH 连接 MySQL 服务器的用户名。 |
ssh_key |
SSH 连接 MySQL 服务器的私钥文件路径。 |
master_binlog_dir |
Master 节点的二进制日志目录。 |
candidate_master |
指定候选 Master 的主机名或 IP 地址。 |
preferred_master_candidate |
优先选择的 Master 候选节点。 |
no_master_candidate |
不允许作为 Master 候选节点的服务器。 |
master_ip_online_change |
在新的 Master 上线时执行的脚本路径。 |
master_ip_offline_change |
在旧的 Master 下线时执行的脚本路径。 |
secondary_check_script |
在故障检测阶段执行的脚本路径。 |
ping_type |
Master 节点健康检查的方式,可选值包括 ping 、mysql 。 |
ping_interval |
Master 节点健康检查的间隔时间,单位为秒。 |
max_failover_attempts |
最大故障切换尝试次数。 |
report_script |
报警脚本路径,用于发送故障通知。 |
shutdown_script |
关闭旧 Master 的脚本路径。 |
remove_master_relay_log |
是否在故障切换后删除旧 Master 上的 relay log。 |
4.2 node.cnf
常用配置项
配置项 | 说明 |
---|---|
user |
连接 MySQL 服务器的用户名。 |
password |
连接 MySQL 服务器的密码。 |
ssh_user |
SSH 连接 MySQL 服务器的用户名。 |
ssh_key |
SSH 连接 MySQL 服务器的私钥文件路径。 |
port |
MySQL 服务器的端口号。 |
5. 故障切换测试与验证
配置完 MHA 后,需要进行故障切换测试,验证 MHA 是否能够正常工作。
测试步骤:
- 模拟 Master 节点故障,例如停止 MySQL 服务。
- 观察 MHA Manager 是否能够检测到故障。
- 观察 MHA Manager 是否能够自动执行故障切换。
- 验证新的 Master 是否能够正常提供服务。
- 验证 Slave 是否能够从新的 Master 继续复制数据。
- 验证客户端是否能够自动连接到新的 Master。
- 验证自定义脚本是否能够正常执行。
6. MHA 的局限性与替代方案
MHA 是一种优秀的 MySQL 高可用解决方案,但它也有一些局限性:
- 不支持自动创建 Slave: MHA 只能管理已经存在的 Slave,无法自动创建新的 Slave。
- 依赖 SSH 连接: MHA 需要通过 SSH 连接到 MySQL 服务器,这可能会带来安全风险。
- 不支持复杂的拓扑结构: MHA 对拓扑结构有一定的要求,不支持复杂的拓扑结构。
针对 MHA 的局限性,可以考虑使用其他的 MySQL 高可用解决方案,例如:
- MySQL Group Replication: MySQL 官方提供的高可用方案,支持多主复制,数据一致性更高。
- Galera Cluster: 基于 Galera 技术的 MySQL 集群,支持多主复制,数据一致性更高。
- Orchestrator: 另一个开源的 MySQL 高可用解决方案,功能更强大,支持更复杂的拓扑结构。
7. 总结关键要点
MHA 是一种强大的 MySQL 高可用工具,通过自定义脚本,可以灵活地扩展其功能。理解 MHA 的工作原理和配置选项,能够帮助我们构建稳定可靠的 MySQL 集群。在选择高可用方案时,需要根据业务需求和实际情况进行综合考虑。