共计 5355 个字符,预计需要花费 14 分钟才能阅读完成。
目录
- HA 模式地图:从异步复制到多活
- InnoDB Group Replication(单主 / 多主)核心机制
- InnoDB Cluster 快速上手(MySQL Shell)
- ClusterSet 跨地域容灾与流量路由
- Orchestrator 自动故障切换(经典主从架构)
- 半同步复制:一致性与吞吐的权衡
- 读写一致性与读偏防护(强制主读、会话线性化)
- 跨机房 / 跨云设计:RTO/RPO、延迟与双活策略
- 灾备演练与混沌注入:脚本化与验收清单
- 数据完整性与闪回:校验、PITR、Clone 快速恢复
- 流量切换策略:DNS/Proxy/Router/ 服务网格
- 实战练习(含参考答案)
版本:MySQL 8.0。示例在本地或云环境均可按需调整。仍沿用
shop库。
1) HA 模式地图:从异步复制到多活
- 异步复制(Async):最常见;RPO>0(主库故障可能丢失尚未复制的事务)。
- 半同步(Semi-sync):主库提交需 ≥1 副本确认 binlog 写入;降低丢失概率。
- Group Replication(MGR):基于写集合(Write-Set)冲突检测,成员一致协议;支持 单主模式 (Single-Primary)与 多主模式(Multi-Primary)。
- InnoDB Cluster/ClusterSet:在 MGR 之上提供编排、元数据与路由;ClusterSet 支持跨地域主集群与灾备集群的角色切换。
选型口诀:先简单后复杂。典型 OLTP:读写分离 + 半同步 → 需要“无脑切主”再上 Orchestrator → 多 AZ/ 多机房再评估 InnoDB Cluster/ClusterSet。多主写仅在确有强需求且冲突可控时考虑。
2) InnoDB Group Replication(单主 / 多主)核心机制
关键点:
- GTID 强制开启;事务写集合
transaction_write_set_extraction=XXHASH64;成员通过共识协议(组通信)决定提交顺序。 - 冲突检测:基于主键 / 唯一键哈希,冲突事务在副本侧被拒绝(多主时尤需注意幂等与重试)。
- 一致性等级(
group_replication_consistency):EVENTUAL(默认):最终一致;BEFORE_ON_PRIMARY_FAILOVER:切主前阻塞,保证读到最新;BEFORE/AFTER/BEFORE_AND_AFTER:控制读 / 写的线性化成本。
- 单主与多主:
group_replication_single_primary_mode=ON(单主,推荐);多主需评估热点键与写冲突。
最小配置片段(每个节点):
[mysqld]
server_id = 101 # 各节点唯一
gtid_mode = ON
enforce_gtid_consistency = ON
binlog_format = ROW
transaction_write_set_extraction = XXHASH64
# 组配置(示例)loose-group_replication_group_name = "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee" # UUID
loose-group_replication_start_on_boot = OFF
loose-group_replication_local_address = "db1:33061"
loose-group_replication_group_seeds = "db1:33061,db2:33061,db3:33061"
备注:实际还需账户与通道初始化,建议用 MySQL Shell 自动化(见下一节)。
3) InnoDB Cluster 快速上手(MySQL Shell)
步骤:
- 三台实例安装 MySQL 8.0,开放 3306;准备管理账号(如
root)。 - 用
mysqlsh对每台实例执行dba.configureInstance()自动开启必需项。 - 创建集群、加入节点、部署 Router。
// 连接第一台(Primary 候选)\connect root@db1:3306
var opt = {clusterAdmin:"dba", clusterAdminPassword:"Dba@123"}
dba.configureInstance('root@db1:3306', opt)
dba.configureInstance('root@db2:3306', opt)
dba.configureInstance('root@db3:3306', opt)
// 创建集群(单主)var cluster = dba.createCluster('shopCluster')
cluster.addInstance('root@db2:3306')
cluster.addInstance('root@db3:3306')
cluster.status() // 查看拓扑
// 部署 Router(在应用侧主机执行)// shell 外:mysqlrouter --bootstrap root@db1:3306 --directory /opt/router --user mysqlrouter
常用操作:
cluster.setPrimaryInstance('root@db2:3306') // 主动切主
cluster.rejoinInstance('root@db3:3306') // 故障恢复后重入
cluster.status({extended:1})
Router 提供读写路由端口(RW/RO)。强一致读取可在会话层要求“主库读取”(见 §7)。
4) ClusterSet 跨地域容灾与流量路由
场景:A 区域主集群(Primary Cluster)+ B 区域灾备集群(Replica Cluster)。
- 建立 ClusterSet:
// 在主集群上
var cs = dba.createClusterSet(cluster)
cs.addCluster('drCluster', 'root@dr1:3306')
cs.status()
- 切换:当 A 区域不可用,可将
drCluster提升为 Primary;Router 通过元数据自动更新路由目标。 - 注意:跨地域时延高 → 写效率下降;优先单主跨地域复制,避免多主写热点与冲突。
5) Orchestrator 自动故障切换(经典主从架构)
不使用 MGR 的场景下,Orchestrator 可在异步 / 半同步复制拓扑中自动晋升新主。
最小配置 orchestrator.conf.json(示例):
{
"Debug": false,
"MySQLOrchestratorHost": "127.0.0.1",
"MySQLOrchestratorPort": 3306,
"MySQLOrchestratorUser": "orc",
"MySQLOrchestratorPassword": "Orc@123",
"DiscoverByShowSlaveHosts": false,
"InstancePollSeconds": 5,
"RecoveryPeriodBlockSeconds": 300,
"ApplyMySQLPromotionAfterMasterFailover": true,
"RecoveryIgnoreHostnameFilters": ["^test-"]
}
要点:
auto_increment/gtid规范、只在 新主 开启写;- 和负载均衡(VIP/DNS/ProxySQL)联动,切换后更新写入口;
- 预演晋升:拔网线 /kill -9/ 冻结 IO,验证 RTO 与数据一致性。
6) 半同步复制:一致性与吞吐的权衡
开启示例:
-- 主库
INSTALL PLUGIN rpl_semi_sync_source SONAME 'semisync_source.so';
SET GLOBAL rpl_semi_sync_source_enabled = ON;
SET GLOBAL rpl_semi_sync_source_timeout = 1000; -- 1s 等待
-- 副本
INSTALL PLUGIN rpl_semi_sync_replica SONAME 'semisync_replica.so';
SET GLOBAL rpl_semi_sync_replica_enabled = ON;
注意 :超时后自动退化为异步;多副本时只需 至少一个 确认。业务高峰可权衡调低等待,保障尾延迟。
7) 读写一致性与读偏防护(强制主读、会话线性化)
- 强制主读:对写后立即读的请求,路由到 Primary(Proxy/Router 规则或会话 Hint)。
- GTID 安全读:在读副本上等待应用至指定 GTID(某些中间件支持
wait_for_gtid)。 - 会话线性化:将一致性等级设为
group_replication_consistency='BEFORE_AND_AFTER'(代价是延迟上升)。 - 只读保护:非主节点
super_read_only=ON;切主后记得刷新。
8) 跨机房 / 跨云设计:RTO/RPO、延迟与双活策略
- RTO(恢复耗时)与 RPO(可容忍数据丢失窗口)量化到分钟级;
- 同城双 AZ:优先单主写 + 多只读;
- 异地容灾:ClusterSet/ 异步复制到 DR,定期演练;
- 双活:仅在写冲突概率极低、幂等键完备、业务可接受回滚 / 重试时启用(如区域隔离下“各写各的”)。
- 网络与时钟:NTP 同步,故障注入考虑网络分区、抖动、丢包与高时延。
9) 灾备演练与混沌注入:脚本化与验收清单
演练脚本思路:
# 1) 制造主库故障
essh db1 'sudo systemctl stop mysqld'
# 2) 检查中间件反应(Router/ProxySQL/Orchestrator)# 3) 观测:RTO、错误率、p99 延迟、复制追平时间
# 4) 恢复:重启、补数据、rejoin 节点
验收清单:
- 切换期间写入是否阻断 / 幂等保护是否生效;
- 读流量是否自动指向健康节点;
- 切回是否平滑(连接耗尽、连接池重建)。
10) 数据完整性与闪回:校验、PITR、Clone 快速恢复
- 一致性校验:
pt-table-checksum对比主从;或按主键区间计算(COUNT,SUM,MAX(updated_at))作为校验和(见第七课 §9)。 - PITR 自动化:全量备份 + binlog 回放脚本(参见第三课 §4.3)。
- Clone:在新实例上快速克隆(用于快速拉起新副本 / 演练环境)。
- 数据闪回 :无“原地闪回”,实务用 延迟复制 或 binlog 闪回脚本 恢复误操作。
11) 流量切换策略:DNS/Proxy/Router/ 服务网格
- DNS:简单但缓存不确定;适合灰度或大粒度切换。
- VIP/Keepalived:快速主库漂移;需网络层支持。
- ProxySQL:规则化路由、权重、故障摘除(与 Orchestrator/MGR 联动)。
- MySQL Router:InnoDB Cluster 官方路由;自动发现主从、提供 RW/RO 端口。
- Service Mesh:以 Sidecar 实现断路、重试、超时与灰度(需注意幂等语义)。
12) 实战练习(含参考答案)
练习 1(MGR 单主):写出三节点的最小 MySQL Shell 命令,创建名为 shopCluster 的单主集群,并将 db2 切为主。
\connect root@db1:3306
var c = dba.createCluster('shopCluster')
c.addInstance('root@db2:3306')
c.addInstance('root@db3:3306')
c.setPrimaryInstance('root@db2:3306')
练习 2(半同步):在经典主从上开启半同步,设置主库等待 800ms,超时退化异步。
INSTALL PLUGIN rpl_semi_sync_source SONAME 'semisync_source.so';
SET GLOBAL rpl_semi_sync_source_enabled = ON;
SET GLOBAL rpl_semi_sync_source_timeout = 800;
INSTALL PLUGIN rpl_semi_sync_replica SONAME 'semisync_replica.so';
SET GLOBAL rpl_semi_sync_replica_enabled = ON;
练习 3(读偏防护):描述如何保证“用户下单后立即查看订单详情”一定读到最新数据。
答案要点:该请求强制路由到主(RW 端口或 Proxy 规则);或在从库上 wait-for-GTID 应用到下单事务对应位点后再读。
练习 4(Orchestrator 演练):给出一条“拔主库网线”后的自动晋升验证步骤与通过标准。
答案要点:观察 RTO、错误率;新主可写、从库重新建链;负载均衡更新写入口;数据一致性校验通过。
练习 5(跨地域演练):基于 ClusterSet,将 DR 集群提升为主并验证回切流程。
答案要点:promote DR → Router 元数据刷新 → 灰度恢复流量 → 比对校验和 → 视窗口与积压量决定回切 / 就地继续。
小结
- 高可用不是某个“开关”,而是一套 架构 + 流程 + 演练。
- 优先单主与半同步,复杂到一定程度再引入 MGR/ClusterSet。
- 读写一致性要与业务场景对齐;强一致路径要明确且可观测。
- 灾备的价值在于 定期演练 与事后可复盘,把 RTO/RPO 写进 SLO 并压测验证。

