2. 副本与复制:同步复制与异步复制的原理与对比

聊到多副本,绕不开的核心就是「复制」——怎么把一份数据同步到其他节点上去。这里有两个最基础的模式:同步复制和异步复制。不是哪个更好,而是看场景怎么选。我这几年做过的系统里,因为选错复制模式导致线上事故的,少说也有三四回了。

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

同步复制的逻辑其实很直白:只有所有副本都写成功了,才算写成功。 客户端发起写请求,主节点必须等所有从节点都返回确认,再回复客户端「OK」。

核心特征:

  • 强一致性:读写都是最新值
  • 高延迟:最慢的节点决定响应时间
  • 低可用:一个从节点挂了,写入就阻塞

我在做金融系统时,选的就是同步复制。交易记录少一条就是损失,不能用「最终一致」来糊弄。但代价也明显——有一次MySQL从节点磁盘打满,主库的写入请求直接全部超时,差点引发雪崩。

2.2 异步复制:性能优先的妥协

异步复制正好反过来:主节点写完了就马上告诉客户端「成功」,复制到从节点的操作放到后台去做。 客户端不管从节点是否写完。

核心特征:

  • 最终一致性:短时间可能读到旧数据
  • 低延迟:不受从节点性能影响
  • 高可用:主节点不依赖从节点状态

大部分互联网业务用的是异步复制。比如发微博、点赞、评论,丢失几毫秒的数据,用户完全感知不到。但你想想看——万一主节点挂了,那部分还没同步的数据就彻底丢了。

我曾经… 遇到过一个案例:某团队做用户会话缓存,选了异步复制。主库宕机后,所有新登录的用户会话全部丢失,几千人同时被踢下线。痛点就是「丢了不可接受的数据」。

2.3 核心对比:一张表说清楚

对比维度 同步复制 异步复制
一致性 强一致性 最终一致性
写延迟 高(等待最慢节点) 低(只写主节点)
数据安全 主节点故障,数据不丢 主节点故障,可能丢数据
可用性 低(从节点故障影响写) 高(从节点故障不影响写)
适用范围 金融、交易、元数据 日志、缓存、社交、大数据

个人习惯:我通常会把这个表贴在团队的白板上。选复制模式时先问一句:「丢了最后几秒的数据,业务受不受得了?」受得了就异步,受不了就同步。

2.4 复制流程对比(SVG)

下面这张图把两种模式的核心流程画在一起,方便你对比理解。

同步复制 vs 异步复制 流程对比 同步复制 异步复制 客户端 主节点 从节点1 从节点2 ① 写请求 ② 同步复制 ② 同步复制 ③ 确认 ③ 确认 ④ 返回成功 所有从节点确认后 才告诉客户端「写完了」 客户端 主节点 从节点1 从节点2 ① 写请求 ② 立即返回成功 ③ 后台复制 ③ 后台复制 主节点写完就告诉客户端 复制到从节点…慢点再说

简单解释一下这张图。左边同步复制:客户端等主节点,主节点等所有从节点,确认消息一条都不能少。右边异步复制:客户端只管写,从节点什么时候收到——那是主节点自己的事,后台慢慢推过去就行。

2.5 半同步复制:折中的方案

我个人习惯在「不能丢数据,但又受不了同步的高延迟」的场景下,用半同步复制。比如MySQL的semi-sync replication。

半同步的核心思路:主节点至少等一个从节点确认,就返回成功。 不要求所有从节点都写完。这样做的好处是:既保证了一定程度的数据安全,又不会让写入延迟被最慢的那个从节点拖死。

2.6 选型建议:我的实践经验

  1. 金融交易、库存、订单 → 同步复制或半同步。数据一致性高于一切。
  2. 日志、监控、大数据 → 异步复制。丢了无所谓,整体往前跑。
  3. 缓存、会话 → 异步复制,但得加一个兜底——比如Redis的主从故障时,丢掉的key可以从数据源重建。

我曾经… 在一家电商公司看到他们把所有MySQL都配了同步复制。结果大促时一个从节点慢查询导致全库写入超时。后来我强制要求:核心交易库用半同步,非核心库全部切异步。压测下来,写入RT直接降了60%。

记住一个原则:没有完美的复制模式,只有适合你业务的复制模式。同步换一致性,异步换性能,半同步就是那个「既要…又要…」的折中怪。