MySQL高可用架构与自动故障切换实战:Orchestrator与Consul集成的工程化部署

MySQL高可用为什么还在反复踩坑?

MySQL高可用方案经历过几代演进:MHA、MMM早已过时, Orchestrator + Consul 是当前社区认可度最高的组合方案。但选对工具只是第一步——故障切换流程怎么设计、复制拓扑怎么配、切换后的数据一致性怎么验证,这些才是真正决定高可用能不能扛住生产事故的环节。

这篇文章从工程化视角,把Orchestrator和Consul集成的部署全流程拆开讲。

方案对比:为什么选Orchestrator

主流MySQL高可用方案横向对比:

| 方案 | 自动切换 | 拓扑感知 | 冗余切换保护 | 社区活跃度 |
|——|———|———|————-|———–|
| MHA | 半自动 | 无 | 无 | 停更 |
| MySQL InnoDB Cluster | 有 | Group Replication | 有 | 活跃 |
| Orchestrator | 有 | 完整拓扑图 | 有 | 活跃 |

Orchestrator的核心优势在于拓扑感知——它持续探测集群中每个节点的复制关系,维护一张实时拓扑图。发生故障时,它基于拓扑图找到最合适的从库提升为新主库(数据最新、复制延迟最小),而不是简单地把第一个从库切上去。

另外,Orchestrator支持恢复钩子——切换前后执行自定义脚本,可以集成Consul做服务发现更新、发告警通知、执行应用层重连逻辑。

Orchestrator部署与配置

Orchestrator的配置文件是JSON格式,以下是生产级配置:

{
  "Debug": false,
  "ListenAddress": ":3000",
  "MySQLTopologyUser": "orchestrator_topo",
  "MySQLTopologyPassword": "topo_password",
  "MySQLTopologyCredentialsConfigFile": "",
  "MySQLTopologySSL": false,
  "BackendDB": "mysql",
  "MySQLOrchestratorHost": "127.0.0.1",
  "MySQLOrchestratorPort": 3306,
  "MySQLOrchestratorDatabase": "orchestrator",
  "MySQLOrchestratorUser": "orchestrator",
  "MySQLOrchestratorPassword": "orch_pass",
  "ReplicationCredentials": true,
  "DetectSemiSyncMaster": true,
  "DetectSemiSyncSlave": true,
  "RecoveryPeriodBlockSeconds": 60,
  "RecoveryIgnoreHostnamePatterns": [],
  "FailMasterPromotionSQL": ["SET GLOBAL read_only=0"],
  "PostMasterFailoverProcesses": [
    "/usr/local/bin/post_failover.sh {failedHost} {successorHost} {successorIp}"
  ],
  "PostUnsuccessfulFailoverProcesses": [
    "/usr/local/bin/failover_failed_alert.sh {failedHost}"
  ],
  "ApplyMySQLPromotionAfterMasterFailover": true,
  "MasterFailoverLostInstancesDowntimeMinutes": 10,
  "DetachLostSlavesAfterMasterFailover": true,
  "CheckReplicationFilters": true,
  "CheckReplicationLag": true,
  "SkipMaxScaleCheck": true
}

关键配置项解释:

RecoveryPeriodBlockSeconds: 60:切换后60秒内不再触发新的恢复,防止脑裂场景下反复切换
DetectSemiSyncMaster/Slave:开启半同步复制检测
PostMasterFailoverProcesses:切换成功后执行的钩子脚本(后面详细讲)

故障切换三阶段流程

Orchestrator的故障切换分三个阶段:检测决策执行

检测阶段:Orchestrator通过持续的HTTP探测和MySQL连接检查监控主库存活状态。默认连续探测失败3次(间隔1秒)认定主库宕机,触发恢复流程。

决策阶段:从拓扑图中筛选候选从库,按以下优先级排序:
1. 启用了半同步复制的从库(数据更完整)
2. 复制延迟最小的从库(Seconds_Behind_Master
3. 与主库binlog差异最小的从库
4. 同机房/同可用区的从库

执行阶段
1. 在候选从库上执行STOP SLAVE; RESET SLAVE ALL;
2. 设置新主库read_only=0
3. 将其余从库CHANGE MASTER TO指向新主库
4. 执行PostMasterFailoverProcesses钩子脚本

Consul集成:让应用无感切换

主库切换后,应用需要知道新主库的地址。通过Consul的服务发现机制,应用不再直连MySQL IP,而是连接Consul的Service Name(如 mysql-master.service.consul),DNS解析到当前主库IP。

切换钩子脚本负责更新Consul中的服务注册:

#!/bin/bash
# /usr/local/bin/post_failover.sh
# Orchestrator主库切换后的Consul注册更新
# 参数: failedHost successorHost successorIp

FAILED_HOST=$1
SUCCESSOR_HOST=$2
SUCCESSOR_IP=$3
CONSUL_ADDR="127.0.0.1:8500"
SERVICE_NAME="mysql-master"

echo "[$(date)] 故障切换: ${FAILED_HOST} -> ${SUCCESSOR_HOST} (${SUCCESSOR_IP})"

# 1. 注销旧主库的Consul服务注册
curl -s --request PUT "http://${CONSUL_ADDR}/v1/agent/service/deregister/${SERVICE_NAME}-${FAILED_HOST}"

# 2. 注册新主库
cat > /tmp/consul_mysql.json <<EOF
{
  "ID": "${SERVICE_NAME}-${SUCCESSOR_HOST}",
  "Name": "${SERVICE_NAME}",
  "Address": "${SUCCESSOR_IP}",
  "Port": 3306,
  "Tags": ["master", "mysql", "writable"],
  "Check": {
    "Interval": "5s",
    "Timeout": "3s",
    "TCP": "${SUCCESSOR_IP}:3306"
  }
}
EOF

curl -s --request PUT "http://${CONSUL_ADDR}/v1/agent/service/register" -d @/tmp/consul_mysql.json

# 3. 发送告警
curl -s -X POST "https://hooks.example.com/alert" \
  -H "Content-Type: application/json" \
  -d "{\"text\": \"MySQL主库切换完成: ${FAILED_HOST} -> ${SUCCESSOR_HOST}\"}"

echo "Consul注册更新完成"

应用侧连接配置示例(Spring Boot):

spring:
  datasource:
    url: jdbc:mysql://mysql-master.service.consul:3306/app_db?useSSL=false
    # Consul DNS会解析到当前主库IP,切换后自动生效
    hikari:
      maximum-pool-size: 20
      connection-timeout: 3000
      # 连接验证+快速失败,切换后秒级恢复
      validation-timeout: 1000

半同步复制与GTID配置

异步复制存在主库宕机后从库丢数据的风险,半同步复制要求至少一个从库确认收到binlog后主库才commit,大幅降低数据丢失概率。

my.cnf关键配置:

# my.cnf — 主库配置
[mysqld]
server-id = 1
log-bin = mysql-bin
binlog-format = ROW
gtid-mode = ON
enforce-gtid-consistency = ON

# 半同步复制
plugin-load = "rpl_semi_sync_master=semisync_master.so"
rpl_semi_sync_master_enabled = 1
rpl_semi_sync_master_timeout = 3000
rpl_semi_sync_master_wait_for_slave_count = 1

# 复制稳定性
sync-binlog = 1
innodb-flush-log-at-trx-commit = 1
binlog-checksum = CRC32
# my.cnf — 从库配置
[mysqld]
server-id = 2
log-bin = mysql-bin
binlog-format = ROW
gtid-mode = ON
enforce-gtid-consistency = ON
relay-log = relay-bin
log-slave-updates = ON
read-only = ON

# 半同步从库
plugin-load = "rpl_semi_sync_slave=semisync_slave.so"
rpl_semi_sync_slave_enabled = 1

rpl_semi_sync_master_timeout = 3000 意味着主库等待3秒超时后降级为异步复制——这是在数据安全性和可用性之间的权衡,3秒足够覆盖大多数网络抖动场景。

备份恢复验证:切换后的最后防线

高可用架构里的备份恢复经常被忽视——切换成功不代表数据完整,需要定期验证备份可恢复性。

xtrabackup全量+增量备份脚本:

#!/bin/bash
# MySQL xtrabackup备份脚本
# 用法: backup_mysql.sh full|incr
# 周日全量,周一至周六增量

BACKUP_DIR="/data/mysql-backup"
DATE=$(date +%Y%m%d)
DAY_OF_WEEK=$(date +%u)  # 1=周一, 7=周日
MYSQL_USER="backup_user"
MYSQL_PASS="backup_pass"
MYSQL_CMD="xtrabackup --user=${MYSQL_USER} --password=${MYSQL_PASS}"

mkdir -p ${BACKUP_DIR}/${DATE}

if [ "$1" = "full" ] || [ ${DAY_OF_WEEK} -eq 7 ]; then
    echo "[$(date)] 执行全量备份..."
    ${MYSQL_CMD} --backup --target-dir=${BACKUP_DIR}/${DATE}/full \
        --parallel=4 --compress
    # 记录全量备份路径供增量使用
    echo "${BACKUP_DIR}/${DATE}/full" > ${BACKUP_DIR}/.last_full
else
    LAST_FULL=$(cat ${BACKUP_DIR}/.last_full 2>/dev/null)
    if [ -z "${LAST_FULL}" ]; then
        echo "[ERROR] 未找到全量备份记录,先执行全量备份"
        exit 1
    fi
    echo "[$(date)] 执行增量备份,基于: ${LAST_FULL}"
    ${MYSQL_CMD} --backup --target-dir=${BACKUP_DIR}/${DATE}/incr \
        --incremental-basedir=${LAST_FULL} --parallel=4 --compress
fi

# 清理7天前的备份
find ${BACKUP_DIR} -maxdepth 1 -type d -mtime +7 -exec rm -rf {} \;
echo "[$(date)] 备份完成"

恢复验证建议每周在隔离环境执行一次:把全量+增量备份恢复到测试库,运行 mysqlcheck --all-databases --check 验证表完整性,用 pt-table-checksum 对比生产与恢复数据的一致性。备份不验证等于没备份。

Orchestrator+Consul这套组合在生产环境中已被大量验证,核心是三个环节:拓扑感知选主准确、Consul服务发现让应用无感切换、半同步复制+GTID保障数据完整性。把切换钩子脚本、Consul注册更新和备份验证流程都跑通,高可用才能真正扛住故障。

原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/mysql-gao-ke-yong-jia-gou-yu-zi-dong-gu-zhang-qie-huan-shi/

(0)
小编小编
上一篇 17小时前
下一篇 17小时前

相关推荐