18.7 复制拓扑 (链式 / 树形 / 星形)

一句话

拓扑决定 “延迟怎么叠加、带宽压在哪”:星形一跳最快(20ms)但主库要发 N 份,链式最省带宽但延迟随跳数累加(5 跳 100ms),树形折中(3 跳 60ms)——没有最好,只有 “你的瓶颈是主库带宽还是尾副本延迟”。

三种拓扑(本机按每跳 20ms 估算)

拓扑 最大跳数 尾副本滞后 主库出流量 适合
星形(主 → 所有从) 1 ≈20ms N 份(带宽压力大) 从库少、要低延迟
树形(主 → 中继 → 叶) 3 ≈60ms 扇出(可控) 跨机房/多地域
链式(A → B → C…) 5 ≈100ms 1 份(最省) 带宽紧张、能容忍延迟
尾副本滞后 ≈ 跳数 × 每跳延迟
主库出流量 ≈ 副本数 × 日志速率(星形)vs 中继数(树形)vs 1(链式)

选择判据

你的瓶颈 选择 理由
主库出口带宽 链式/树形 减少主库扇出
尾副本读延迟 星形 跳数最少
跨地域灾备 树形(按地域中继) 避免跨洋多份复制
多活/写扩散 多主(见 18.1 复制模型:单主 / 多主 / 无主) 拓扑无法解决写冲突

代码:树形拓扑的配置要点

# 主库只发给同机房中继,跨地域由中继再分发(减少主库跨洋流量)
# 主 → relay-1(同机房)
log_bin = ON
binlog_do_db = app
# relay-1 → 地域 B 的从库
# (在 relay-1 上开启 log_slave_updates,让从库能继续向下游复制)
log_slave_updates = ON
-- 检查“每一跳”的延迟,而不是只看末级
SHOW REPLICA STATUS;   -- 关注 Seconds_Behind_Source / 位点差

反模式

反模式 后果
链式拓扑用于 “低延迟读” 尾副本滞后随跳数累加,越深越慢
星形拓扑用于几十个从库 主库出口带宽打满,影响写入
中继节点不监控 中继挂 = 下游全断,且难定位
跨地域直接星形复制 主库承担全部跨洋流量,成本高
拓扑变更不做演练 切换/扩容时才发现延迟不达标
只监控末级延迟 不知道是哪一跳慢

三条铁律

🔑 延迟按跳数累加;要低延迟就减少跳数。

🔑 带宽压力在主库扇出;从库多就用中继。

🔑 每一跳都要监控,否则定位不到瓶颈。

自检

Q1 为什么链式拓扑 “省带宽” 却 “延迟高”?

▸ 答案:因为链式每级只发给下一个节点,主库出流量只有 1 份(省带宽);但日志要逐跳重放,尾副本的滞后 = 跳数 × 每跳延迟。跳数越多,尾副本越慢,且中间任何一跳故障都会阻断下游。

Q2 树形拓扑的 “中继” 有什么风险?

▸ 答案:中继是单点:它挂了,整棵子树都断流;而且中继需要 log_slave_updates 才能继续向下游复制,配置错误会导致 “下游永远追不上”。所以中继要监控、要能快速替换(或做双中继)。

Q3 星形拓扑什么时候会压垮主库?

▸ 答案:当 从库数量 × 日志速率 超过主库出口带宽时:每个从库都要一份完整日志,几十个从库就是几十倍出流量。表现是 “主库写入正常但复制延迟飙升”“网络打满”。此时应改树形,用中继分担扇出。

Q4 跨地域复制为什么常用 “树形 + 地域中继”?

▸ 答案:因为跨洋带宽贵且延迟高:让主库只发同机房中继,再由中继分发到各地域,可以把 “N 份跨洋流量” 降为 “1 份”。代价是多一跳延迟(可接受,因为跨洋本来就有延迟)。

Q5 拓扑和 “一致性” 有关系吗?

▸ 答案:间接有:跳数越多,尾副本越旧,读一致性的窗口越大(见 18.4 复制延迟与读一致性);但一致性级别由 “同步/异步” 决定,不由拓扑决定。拓扑影响的是 “延迟分布”,不是 “是否可能丢数据”。

Q6 多主(multi-master)能解决拓扑问题吗?

▸ 答案:不能,它只是把 “复制延迟” 换成 “写冲突”:多主之间仍要复制,冲突要靠版本/CRDT/人工解决。拓扑解决 “怎么分发”,多主解决 “哪里能写”,两者是不同维度的问题。

Q7 如何验证拓扑是否合适?

▸ 答案:压测 + 观测:测 每跳延迟、尾副本滞后 P99、主库出口带宽。如果尾副本 P99 超标 → 减跳数;如果主库带宽打满 → 加中继。只看 “平均延迟” 会掩盖尾副本的问题。

关联