3. 同步复制与异步复制:延迟、风险与折中方案
聊副本复制,绕不开一个核心问题:到底要不要等?
主库写完数据后,是必须等从库确认收到,还是先告诉客户端“写完了”,回头再慢慢同步?这两种选择,就是同步复制和异步复制的本质区别。我这些年见过太多系统因为选错复制模式而翻车,今天咱们就把这事彻底掰扯清楚。
3.1 同步复制:强一致性的代价
同步复制的逻辑很简单:主库必须等所有(或指定数量的)从库确认写入成功后,才向客户端返回成功。
核心流程:
- 客户端写入主库
- 主库将数据同步写入所有从库
- 所有从库返回 ACK
- 主库向客户端返回成功
听起来很靠谱对吧?但代价也很明显——延迟。
我记得有一次帮一家金融公司做架构评审,他们用了全同步复制。业务高峰期,一次写入的响应时间从 2ms 飙到了 50ms。为什么?因为其中一个从库部署在另一个城市,网络往返就要 30ms。客户端等得花儿都谢了。
同步复制的延迟主要由三部分组成:
| 延迟来源 | 说明 | 典型值 |
|---|---|---|
| 网络往返 | 主库到从库的 RTT | 同机房 0.1-0.5ms,跨机房 10-50ms |
| 写入耗时 | 从库写入磁盘的时间 | 0.5-2ms(SSD) |
| 确认排队 | 等待最慢从库的 ACK | 取决于最慢节点 |
说白了,同步复制的延迟 = 最慢从库的响应时间。你想想看,只要有一个从库慢,整个写入就被拖慢了。
避坑指南:我曾经见过一个团队,把同步复制用在跨洲际的灾备场景。主库在美西,从库在新加坡,每次写入都要等 200ms 以上的网络延迟。结果业务接口 P99 延迟直接爆炸。同步复制不是不能用,但别让慢节点拖累全局。
3.2 异步复制:高性能背后的风险
异步复制就完全相反了。主库写完本地就立刻返回成功,后台线程慢慢把数据推给从库。
核心流程:
- 客户端写入主库
- 主库立即返回成功
- 后台异步将数据同步到从库
这样做的好处很明显——吞吐量高、延迟低。主库不用等任何人,写入性能几乎不受副本数量的影响。
但风险呢?数据丢失。
我亲身经历过一次事故。当时一个电商系统用了异步复制,主库突然宕机。重启后发现,最后 2000 笔订单还没同步到从库。虽然最终通过 binlog 找回了大部分数据,但那几小时的业务中断,损失可不小。
异步复制的风险场景:
- 主库宕机:未同步的数据直接丢失
- 网络分区:从库长时间收不到更新,数据滞后严重
- 主库磁盘损坏:数据彻底丢失,从库也救不回来
你可能会问:那为什么还要用异步复制?
因为大多数场景下,性能比强一致性更重要。比如社交媒体的 feed 流、日志收集系统,丢几条数据问题不大,但响应慢了用户直接流失。
3.3 半同步复制:折中的艺术
同步复制太慢,异步复制太险。有没有中间方案?半同步复制就是答案。
半同步复制的核心思想:主库只要等到至少一个从库确认写入,就返回成功。其他从库可以继续异步同步。
核心流程:
- 客户端写入主库
- 主库将数据写入所有从库
- 等待至少 N 个从库返回 ACK(通常 N=1)
- 主库向客户端返回成功
这样做的好处很明显:
- 延迟可控:只等最快的那个从库,而不是最慢的
- 数据安全:至少有一个副本持有最新数据
- 吞吐量较高:比全同步好得多
我个人习惯在生产环境中优先考虑半同步复制。它不像全同步那样拖垮性能,也不像异步那样裸奔。MySQL 的 semi-sync replication、MongoDB 的 majority write concern,本质上都是这个思路。
经验之谈:配置半同步复制时,我建议把确认节点数设为 1。如果设成 2,其实又回到了全同步的老路——你得等两个从库都确认。另外,一定要设置超时机制。如果从库迟迟不响应,自动降级为异步复制,避免主库被阻塞。
3.4 三种模式对比
| 特性 | 同步复制 | 异步复制 | 半同步复制 |
|---|---|---|---|
| 数据一致性 | 强一致 | 最终一致 | 较强一致 |
| 写入延迟 | 高(等最慢节点) | 低(不等) | 中(等最快节点) |
| 吞吐量 | 低 | 高 | 中高 |
| 数据丢失风险 | 几乎为零 | 高 | 低(最多丢一个节点) |
| 适用场景 | 金融、交易 | 日志、缓存 | 大多数业务系统 |
3.5 核心逻辑图
下面这张图展示了三种复制模式的核心差异。注意看主库返回成功的时间点——这是理解它们区别的关键。
3.6 如何选择?
没有银弹。我一般这样选:
- 金融、交易、支付:用同步复制,或者半同步复制 + 多数派确认。数据一致性是命根子。
- 普通业务系统:半同步复制,确认节点数设为 1。性能和安全的平衡点。
- 日志、缓存、非关键数据:异步复制。丢了也不心疼,性能优先。
一个小技巧:很多数据库支持动态切换复制模式。我习惯在白天业务高峰期用半同步,夜间低峰期切到全同步做数据校验。既保证了性能,又兼顾了数据安全。