4. 复制与一致性:主从复制、多主复制、无主复制,读写quorum机制

复制,说白了就是把数据拷贝到多台机器上。为什么要这么做?你想想看,一台机器挂了,数据就丢了,服务就断了。多放几台,一台挂了还有别的顶着。但问题来了——怎么保证这些副本之间的数据是一致的?

我这些年做分布式系统,见过太多因为复制策略选错而翻车的案例。有人为了追求强一致性,把系统搞成了单点瓶颈;有人为了性能,结果数据对不上,业务方天天来投诉。嗯,这里面的门道,咱们今天好好捋一捋。

4.1 主从复制(Single-Leader Replication)

这是最经典的模式,也是我入行时接触的第一种复制方式。说白了,就是选一个老大(Leader),其他都是小弟(Follower)。

工作流程:

  • 所有写操作必须走Leader
  • Leader把写操作记录到日志里
  • Follower从Leader拉取日志,回放执行
  • 读操作可以走Leader,也可以走Follower

核心要点:写操作是单点的,读操作可以分散。这其实是一种「读写分离」的雏形。

我在项目中遇到过这样一个场景:一个电商系统的订单库,用了MySQL主从复制。平时好好的,但一到双十一大促,从库的延迟就飙到十几秒。用户下单后查订单,发现「订单不存在」,客服电话被打爆了。后来怎么解决的?我们加了一个「读主库」的开关,对关键订单查询强制走主库。

我的建议:主从复制适合「读多写少」的场景。如果业务对一致性要求极高(比如金融交易),建议所有读也走主库,或者用后面要讲的quorum机制。

4.2 多主复制(Multi-Leader Replication)

一个Leader不够用怎么办?那就搞多个。每个节点都能写,然后互相同步。听起来很美好,但坑也不少。

典型场景:

  • 多数据中心部署:每个数据中心一个Leader,减少跨机房延迟
  • 离线客户端:比如手机上的笔记App,离线时本地就是Leader,联网后同步
  • 协作编辑:Google Docs那种,多人同时编辑一个文档

最大的坑:写冲突。

两个Leader同时修改同一条数据,怎么办?比如用户A在纽约改了用户名,用户B在伦敦也改了同一个用户名。等两边同步时,冲突就来了。

我曾经踩过的坑:在一个IM系统中用了多主复制,两个用户同时修改群名称,结果同步后群名称在两个客户端上显示不一样。用户投诉说「你们系统有bug」。后来我们引入了「最后写入者获胜(LWW)」策略,但代价是会丢数据。没有完美的方案,只有适合业务的方案。

常见的冲突解决策略:

策略 说明 缺点
最后写入者获胜(LWW) 以时间戳最新的为准 时钟不同步时会丢数据
版本向量 记录每个节点的版本号 实现复杂,冲突需要人工处理
CRDT(无冲突数据类型) 数学上保证合并结果一致 只适用于特定数据结构

4.3 无主复制(Leaderless Replication)

没有老大,大家都是平等的。客户端直接向所有节点发请求,谁响应快就用谁的数据。最典型的代表就是Amazon的Dynamo和它的开源实现Cassandra。

工作方式:

  • 写操作:客户端向所有节点发写请求,等N个节点确认就算成功
  • 读操作:客户端向所有节点发读请求,取最新的版本
  • 节点挂了?没关系,其他节点顶上

我个人习惯把无主复制比作「菜市场买菜」——你问一圈价格,挑最便宜的买。但问题是,如果某个摊主给你的价格是昨天的,你就买贵了。

4.4 读写Quorum机制

Quorum这个词,说白了就是「法定人数」。在分布式系统里,它解决的是「到底要等多少个节点确认,才算读写成功」的问题。

三个关键参数:

  • N:副本总数
  • W:写操作需要确认的节点数
  • R:读操作需要读取的节点数

核心公式:只要满足 W + R > N,就能保证读操作一定能读到最新的写入数据。

为什么?你想想看,写操作确认了W个节点,读操作读了R个节点。如果W+R>N,那这R个节点里至少有一个是包含最新数据的。这就是所谓的「读己之写」一致性。

常见的配置组合:

配置 W R 特点
强一致性 N 1 写慢,读快,但写失败概率高
最终一致性 1 1 读写都快,但可能读到旧数据
折中方案 N/2+1 N/2+1 读写性能均衡,容错性好

我的经验:生产环境中,我一般用W=2, R=2, N=3。这样既能容忍一个节点故障,又能保证强一致性。如果业务允许最终一致性,我会把W和R都设为1,性能最好。

4.5 三种复制方式的对比

特性 主从复制 多主复制 无主复制
写性能 中等(单点瓶颈) 高(多点写入) 高(并行写入)
读性能 高(可扩展从库) 取决于Quorum配置
一致性保证 强(读主库) 弱(有冲突风险) 可配置(通过Quorum)
容错能力 主库挂了需切换 好(多主互相备份) 最好(无单点)
实现复杂度

最后说一句,没有银弹。选哪种复制方式,取决于你的业务场景。我见过有人为了「技术炫酷」硬上无主复制,结果运维成本高得吓人。也见过有人死守主从复制,结果业务量上来后扛不住。嗯,技术选型这事儿,说白了就是trade-off的艺术。