3273 字
约 10 分钟
15
S15-A05 · 部署拓扑:多机房、单元化与容灾等级

"我们上了双机房"这句话,在故障演练里经常被一句话击穿:主库挂了,从库在另一个机房,但切过去之后全站写失败——因为连接串写死在一个机房、缓存没有预热、异步任务没有消费端。机房数量不是容灾能力,能通过切换验证的拓扑才是。

部署拓扑的决策本质是把 RTO/RPO 换算成"每多一毫秒可容忍的停机,要付多少复杂度与钱"。这篇给出判据:容灾等级怎么定、多活的前置条件、单元化的收益与代价、以及什么情况下多活根本不该做。


1. 先把容灾等级的口径钉死

四种等级常被混着说,判据落在两个指标上:RTO(恢复要多久) 与 RPO(能丢多少数据)。

等级 RTO RPO 典型做法 什么时候够用
备份恢复 小时级 上一次备份到故障点 定期全备 + binlog 归档 内部系统、可容忍回滚
冷备 10–30 分钟 分钟级 待机机器、按需拉起 流量低谷可接受短断
热备 分钟级 秒级 从库实时同步、随时切换 多数对外业务
多活 秒级 / 近零 近零 多机房同时承载流量 支付、登录等不可中断面

比等级更重要的是:RTO/RPO 是谁承诺的。工程侧自拍的 5 分钟,与写进合同、带赔付条款的 5 分钟是两种约束:前者决定架构,后者决定投入。没有承诺方时,最常见的结局是按"越快越好"建设,再为一年用不到一次的能力持续付账单。

2. 多活的三个前置条件

多活不是"多机房部署",而是三件事同时成立。缺一件,故障时就是全站挂。

前置条件 内容 缺失时的失效形态
流量调度 能在秒级把流量从 A 切到 B,且切得回来 故障时手动改 DNS,等 TTL 生效
数据同步 双向或单向复制,延迟可控 切过去读到旧数据或写冲突
冲突处理 同一条记录两边同时写时的裁决规则 数据被覆盖,事后靠人工对账
可用性检验(不是设计检验):
流量能切 × 数据能同步 × 冲突能裁决 × 切回来也是通的 = 多活
任一为否 → 实际是"多机房的热备",按热备的 RTO 承诺

冲突处理的规则通常只有三种:以时间戳为准(要求时钟可比)、以机房优先级为准(简单但会丢另一侧写入)、按业务键分片归属(正确但要改数据模型)。第三种是唯一在强约束业务里站得住的,代价是路由逻辑进了业务代码。

3. 单元化的收益与代价

单元化的思路是:按用户维度切片,每个单元自成闭环,故障只影响一个单元。

维度 收益 代价
故障隔离半径 单单元故障只影响其用户 公共资源(配置、鉴权)仍是全局单点
扩缩粒度 按单元加机器,粒度细 容量规划按单元做,峰谷不均
发布影响面 可分单元灰度 版本必须全员兼容,不能跨单元调用
数据一致性 单元内事务简单 跨单元查询几乎不可行,需要汇总层

单元化卖的是隔离半径,不是性能。隐性成本在于"任何跨单元需求都要重新设计":全局排行榜、跨单元搜索、总后台报表,这三类会在之后反复被提出。

4. 同城双活与异地多活

两者常被当成量级差异,其实差在物理距离带来的延迟下限。

维度 同城(数十公里内) 异地(千公里级)
单向 RTT 亚毫秒到数毫秒 数十毫秒
同步复制可行性 可行(代价是写放大) 不可行,只能异步
数据一致性 可做到较强一致 最终一致,必须处理中间态
运维成本 中等 高,跨地域发布与排障复杂
适用 机房级故障、可用区故障 区域级灾难

判据很直接:需要强一致写的地方,异地多活就要付"跨地域确认"的延迟税。一笔支付要等异地确认,就多出几十毫秒,这几十毫秒往往比故障概率更贵。因此常见组合是"同城做强一致双活 + 异地做异步只读"。

5. 数据层的四种方案与失效模式

方案 机制 切换能力 主要失效模式
主备 单向复制,从库只读 手动/半自动提升 提升后旧主回连造成脑裂
双主 双向复制 两侧都可写 自增冲突、写覆盖、复制环路
分片多副本 每片一组副本 片级切换 片间不一致,聚合结果漂移
全局一致性层 共识协议或分布式事务 自动选主 多数派依赖,跨地域时延迟高
# 数据层切换必须显式声明:谁是权威、切换后如何阻止旧主回连
failover:
  mode: manual-confirm          # 自动提升风险高,先人工确认
  quorum: 2/3                   # 多数派门槛
  fence: revoke-old-primary     # 切换后立即撤销旧主写权限
  max-lag-seconds: 5            # 超过则判定为不满足 RPO,拒绝提升

fence 这一步最常被省略,也最容易造成事故:旧主恢复后仍认为自己是主,两边同时写,数据在复制层互相覆盖。提升不是终点,隔离旧主才是。

6. 三层流量切换:切得动与切得回来

流量切换能力分布在三个层次,任一层的"回切"能力缺失,都会把一次演练变成一次事故。

层 切换机制 生效速度 回切难点
DNS 改解析、调 TTL 分钟级到小时级 TTL 缓存、递归服务器缓存
网关 / 负载均衡 改后端池、权重 秒级 会话粘性、健康检查误判
服务发现 注册中心摘除实例 秒级 客户端缓存、长连接未断开

DNS 是最不可靠的一层:TTL 设得再短,递归缓存也会让部分用户长时间指向旧地址。"切得动但回不来"的常见原因是回切时新机房已有写入,两侧都认为自己该接管。

# 演练时同时验证"切过去"与"切回来",两步都要计时
time dig +short +tcp app.example.com
time curl -so /dev/null -w '%{time_total}\n' https://app.example.com/health

7. 故障演练的真实价值

演练的价值不在于"证明能切",而在于暴露流程里没有自动化的那部分。经验上,第一次演练的时间几乎都花在"谁有权按按钮""密码在哪""监控看哪个面板"上,而不是技术切换本身。

演练类型 验证什么 常见结果
单实例摘除 负载均衡与健康检查 通常顺利,无信息量
主库切换 数据层 fence 与提升流程 暴露连接池不重连、DNS 未生效
机房级断流 流量调度 + 容量余量 暴露新机房容量只有 30%
反向切换 回切路径 暴露"回来的路没人走过"
# 一次完整演练必须走完四段,每段单独计时并留痕
# 1 决策  2 切过去  3 观察  4 切回来
date +%s > /tmp/drill.t0
curl -so /dev/null -w '%{http_code}' https://app.example.com/health   # 切后
dig +short app.example.com                                          # 解析是否生效
mysql -N -e "SELECT MAX(delay) FROM monitor.heartbeat"               # 数据面
date +%s > /tmp/drill.t4

必须承认的差异:演练环境不等于生产。数据量、连接数、缓存热度、第三方依赖的真实超时都不同。因此演练结论的正确读法是"流程能否走通",而不是"切换耗时等于 X 秒"。

8. 成本结构与渐进路径

成本项 构成 量级特征
机房 / 云资源 冗余算力常年空闲 与冗余比例线性
跨地域带宽 数据同步 + 跨区调用 常被低估,按流量计费时增长快
人力 双活运维、跨区发布、演练 至少一人力冗余
复杂度税 每次需求都要考虑路由与一致性 长期、隐性、最贵

渐进路径只有一条现实顺序:

第 0 步:备份恢复演练(先证明备份能恢复)
第 1 步:同城机房切换(热备,分钟级 RTO)
第 2 步:单元化拆分(隔离半径)
第 3 步:异地多活(只对必须多活的核心面)

跳过第 0 步直接做多活是最常见的浪费:备份不可恢复时,任何容灾等级都是纸面数字。

9. 度量:三个可验证的数字

指标 定义 采集方式
切换耗时 从决策到流量全部落到新机房的墙钟时间 演练计时,含人工确认时间
数据丢失量 切换点前后差额(按业务键比对) 对账任务,而非估算
演练频率 每季度有效演练次数 有效的标准是"有回切"

第一个指标要包含人工时间。很多团队报的"3 分钟切换"只算了执行脚本的时间,没算从发现故障到有人做决定的那 10 分钟——而后者才是 RTO 的真实组成部分。

10. 排错:五种"切换了仍全站挂"

现象 原因 处理
双机房已上线,故障时仍全站挂 数据层单主,从库从未提升 先演练数据层切换
切过去后大量报错 连接串、密钥、缓存未随流量迁移 列"跟随流量"的资源清单
DNS 改了,部分用户仍打旧机房 递归缓存未过期 网关层切流,DNS 只做兜底
切换成功,回切后数据分裂 两侧同时写,没有 fence 提升后立即撤销旧主写权限
演练 3 分钟,真实恢复 40 分钟 未计入决策与确认时间 计时含人工环节

11. 边界:什么情况本就不该多活

场景 判断 理由
RTO 要求小时级 热备足够 多活的复杂度换不到收益
单区域业务(用户集中一地) 同城热备即可 异地多活无用户收益
数据强一致要求 多活不可行 跨地域确认的延迟税高于收益
团队少于 5 人 不做多活 运维复杂度超出承受能力
第三方依赖单点 先解决依赖 依赖挂了多活也白搭
流量规模小 备份恢复足够 故障窗口内损失有限

最后两条常被忽略:多活能解决"我的机房挂了",不能解决"支付渠道挂了""云厂商的区域级故障"。容灾等级的瓶颈永远在最弱的那个依赖上,先找它,再谈拓扑。


12. 自测

  1. 多活的三个前置条件分别缺失时,故障表现是什么?
  2. 为什么说"多机房部署"不等于多活?
  3. 单元化真正的收益是隔离半径还是性能?它的隐性成本在哪类需求上暴露?
  4. 异地多活做不了强一致写的根本原因是什么物理约束?
  5. 数据层切换里 fence 这一步省略会导致什么?
  6. RTO 指标为什么必须包含人工决策时间?
S15-A05 · 部署拓扑:多机房、单元化与容灾等级
https://www.clxhxhhr.top/posts/6130/
作者
clxstart
发布于
2024-12-31
许可协议
CC BY-NC-SA 4.0
评论
0 条
还没有评论,先写一条吧。