3. 同步复制与异步复制:延迟、风险与折中方案

聊副本复制,绕不开一个核心问题:到底要不要等?

主库写完数据后,是必须等从库确认收到,还是先告诉客户端“写完了”,回头再慢慢同步?这两种选择,就是同步复制和异步复制的本质区别。我这些年见过太多系统因为选错复制模式而翻车,今天咱们就把这事彻底掰扯清楚。

3.1 同步复制:强一致性的代价

同步复制的逻辑很简单:主库必须等所有(或指定数量的)从库确认写入成功后,才向客户端返回成功。

核心流程:

  1. 客户端写入主库
  2. 主库将数据同步写入所有从库
  3. 所有从库返回 ACK
  4. 主库向客户端返回成功

听起来很靠谱对吧?但代价也很明显——延迟。

我记得有一次帮一家金融公司做架构评审,他们用了全同步复制。业务高峰期,一次写入的响应时间从 2ms 飙到了 50ms。为什么?因为其中一个从库部署在另一个城市,网络往返就要 30ms。客户端等得花儿都谢了。

同步复制的延迟主要由三部分组成:

延迟来源 说明 典型值
网络往返 主库到从库的 RTT 同机房 0.1-0.5ms,跨机房 10-50ms
写入耗时 从库写入磁盘的时间 0.5-2ms(SSD)
确认排队 等待最慢从库的 ACK 取决于最慢节点

说白了,同步复制的延迟 = 最慢从库的响应时间。你想想看,只要有一个从库慢,整个写入就被拖慢了。

避坑指南:我曾经见过一个团队,把同步复制用在跨洲际的灾备场景。主库在美西,从库在新加坡,每次写入都要等 200ms 以上的网络延迟。结果业务接口 P99 延迟直接爆炸。同步复制不是不能用,但别让慢节点拖累全局。

3.2 异步复制:高性能背后的风险

异步复制就完全相反了。主库写完本地就立刻返回成功,后台线程慢慢把数据推给从库。

核心流程:

  1. 客户端写入主库
  2. 主库立即返回成功
  3. 后台异步将数据同步到从库

这样做的好处很明显——吞吐量高、延迟低。主库不用等任何人,写入性能几乎不受副本数量的影响。

但风险呢?数据丢失。

我亲身经历过一次事故。当时一个电商系统用了异步复制,主库突然宕机。重启后发现,最后 2000 笔订单还没同步到从库。虽然最终通过 binlog 找回了大部分数据,但那几小时的业务中断,损失可不小。

异步复制的风险场景:

  • 主库宕机:未同步的数据直接丢失
  • 网络分区:从库长时间收不到更新,数据滞后严重
  • 主库磁盘损坏:数据彻底丢失,从库也救不回来

你可能会问:那为什么还要用异步复制?

因为大多数场景下,性能比强一致性更重要。比如社交媒体的 feed 流、日志收集系统,丢几条数据问题不大,但响应慢了用户直接流失。

3.3 半同步复制:折中的艺术

同步复制太慢,异步复制太险。有没有中间方案?半同步复制就是答案。

半同步复制的核心思想:主库只要等到至少一个从库确认写入,就返回成功。其他从库可以继续异步同步。

核心流程:

  1. 客户端写入主库
  2. 主库将数据写入所有从库
  3. 等待至少 N 个从库返回 ACK(通常 N=1)
  4. 主库向客户端返回成功

这样做的好处很明显:

  • 延迟可控:只等最快的那个从库,而不是最慢的
  • 数据安全:至少有一个副本持有最新数据
  • 吞吐量较高:比全同步好得多

我个人习惯在生产环境中优先考虑半同步复制。它不像全同步那样拖垮性能,也不像异步那样裸奔。MySQL 的 semi-sync replication、MongoDB 的 majority write concern,本质上都是这个思路。

经验之谈:配置半同步复制时,我建议把确认节点数设为 1。如果设成 2,其实又回到了全同步的老路——你得等两个从库都确认。另外,一定要设置超时机制。如果从库迟迟不响应,自动降级为异步复制,避免主库被阻塞。

3.4 三种模式对比

特性 同步复制 异步复制 半同步复制
数据一致性 强一致 最终一致 较强一致
写入延迟 高(等最慢节点) 低(不等) 中(等最快节点)
吞吐量 低 高 中高
数据丢失风险 几乎为零 高 低(最多丢一个节点)
适用场景 金融、交易 日志、缓存 大多数业务系统

3.5 核心逻辑图

下面这张图展示了三种复制模式的核心差异。注意看主库返回成功的时间点——这是理解它们区别的关键。

同步/异步/半同步复制流程对比 三种复制模式流程对比 客户端 主库 从库1 从库2 从库3 同步复制: 写入 等待所有 ACK 返回成功 异步复制: 写入 立即返回 后台异步同步 半同步复制: 写入 等最快节点 ACK 返回成功 关键区别: • 同步复制:等所有从库确认 → 强一致,延迟高 • 异步复制:不等任何从库 → 高性能,有丢数据风险 • 半同步复制:等最快从库确认 → 折中方案,推荐大多数场景使用

3.6 如何选择?

没有银弹。我一般这样选:

  • 金融、交易、支付:用同步复制,或者半同步复制 + 多数派确认。数据一致性是命根子。
  • 普通业务系统:半同步复制,确认节点数设为 1。性能和安全的平衡点。
  • 日志、缓存、非关键数据:异步复制。丢了也不心疼,性能优先。

一个小技巧:很多数据库支持动态切换复制模式。我习惯在白天业务高峰期用半同步,夜间低峰期切到全同步做数据校验。既保证了性能,又兼顾了数据安全。