单领导者复制:数据库里的“只有一个话事人”

在分布式数据库的复制世界里,单领导者复制(Single-Leader Replication)是最经典、最常见的一种模式。它就像团队里只有一个决策者,所有重要决定都得经过他。

什么是单领导者复制?

简单来说,单领导者复制就是:

  • 领导者(Leader,也叫 primary/master/source):唯一的写入口,所有写请求都必须发给它。
  • 追随者(Follower,也叫 read replica/secondary/hot standby):只读节点,从领导者那里同步数据,供客户端查询。

下图展示了单领导者复制的基本流程: 客户端将写请求发给领导者,领导者将数据变更同步给追随者;读请求可以发给任意副本。

sequenceDiagram participant Client as 客户端 participant Leader as 领导者 participant Follower1 as 追随者1 participant Follower2 as 追随者2 Client->>Leader: 写请求(例如更新数据) Leader->>Leader: 本地写入 Leader->>Follower1: 复制日志(数据变更) Leader->>Follower2: 复制日志(数据变更) Note over Leader,Follower2: 追随者异步/同步确认 Client->>Leader: 读请求 Leader-->>Client: 返回数据 Client->>Follower1: 读请求 Follower1-->>Client: 返回数据(可能稍旧)

同步还是异步?这是个时间问题

复制可以是同步的,也可以是异步的,区别在于领导者如何等待追随者的确认。

同步复制(Synchronous replication):领导者发出变更后,必须等待所有追随者都回复"已收到",才能告诉客户端"写成功了"。这就像项目经理发完邮件,必须等每个人都回复"收到"才能下班。安全是安全,但如果某个同事上厕所去了(节点故障),整个项目就得等他。

异步复制(Asynchronous replication):领导者发完邮件就直接回家睡觉了,不管对方收没收到。速度快,但风险也大------如果项目经理第二天失忆(节点永久故障),那些没收到邮件的同事就永远不知道真相了。

sequenceDiagram participant Client as 客户端 participant Leader as 领导者 participant FollowerSync as 同步追随者 participant FollowerAsync as 异步追随者 Note over Client,Leader: 同步复制示例(至少一个同步追随者) Client->>Leader: 写请求 Leader->>Leader: 本地写入 Leader->>FollowerSync: 复制日志 FollowerSync-->>Leader: 确认收到 Leader->>FollowerAsync: 复制日志(异步) Note right of FollowerAsync: 不等待确认 Leader-->>Client: 返回成功(仅等待同步追随者) Note over Client,FollowerAsync: 最终一致性问题(从异步追随者读取) Client->>FollowerAsync: 立即读请求 FollowerAsync-->>Client: 返回旧值(尚未同步) Note over Client,FollowerAsync: 片刻后 Client->>FollowerAsync: 再次读请求 FollowerAsync-->>Client: 返回新值(已同步)

数据库界有个折衷方案叫半同步(semi-synchronous):找一个最靠谱的追随者同步确认,其他人异步。这样至少保证数据在两个人手里,不会因为一个人的失忆而全剧终。

新同事入职指南

当系统需要增加新副本(replica)时,比如扩招员工或替换故障节点,怎么让新人快速跟上进度?

总不能直接复制项目经理的硬盘吧?因为他一直在改文件,复制到一半可能数据就乱套了。

标准流程如下:

flowchart LR A[开始设置
新追随者] --> B[获取
领导者快照] B --> C[将快照复制到
新追随者节点] C --> D[新追随者
连接到领导者] D --> E[请求自快照后
所有变更] E --> F[处理变更积压
追赶进度] F --> G{是否赶上} G -- 是 --> H[新追随者开始
正常接收实时变更] G -- 否 --> F

节点挂了怎么办?

分布式系统里,节点宕机是家常便饭。我们需要从容应对。

追随者故障:追赶恢复(Catch-up recovery)

追随者挂了重启后,只需要问项目经理:"我掉线那会儿错过了什么?"然后把错过的变更补上就行。就像看剧暂停去吃饭,回来从暂停处继续------前提是项目经理还留着那段时间的剧情日志(replication log)。如果日志被删了,那新人就得从头再来(从备份恢复)。

领导者故障:故障转移(Failover)

这才是真正的重头戏。当项目经理突然失联(网络问题、宕机、被外星人绑架),系统需要:

  1. 检测到领导者挂了------通常用超时机制,比如30秒没心跳就当死亡。
  2. 选新领导------找那个最了解业务的人(拥有最新数据的追随者)。
  3. 重新配置系统------客户端以后找新老板,旧老板回来也只能当小弟。

这个过程有多刺激?想象一下公司突然宣布原项目经理被解雇,新经理上任,所有人要重新站队......而且这一切可能在30秒内自动完成!

脑裂(Split brain) 是最可怕的------两个节点都以为自己才是真领导。这就像两个人都声称自己是项目负责人,结果团队混乱,数据被搞成一团浆糊。为了避免这种情况,有时得用STONITH(Shoot The Other Node In The Head)------物理上关掉那个误以为自己是领导的节点。这名字很暴力,但确实管用。

复制日志的实现

领导者是怎么把变更告诉追随者的?主要有三种方式。

基于语句的复制(Statement-based replication) :直接把SQL语句发给追随者执行。听起来简单,但问题来了------如果语句用了NOW()RAND(),每个副本会得到不同结果!就像告诉所有人"现在时间",大家低头看表,时间能一样吗?

预写式日志传输(Write-ahead log shipping):把数据库底层的修改日志(WAL)发过去。很底层很可靠,但问题是版本不兼容------你不能让用新版软件的领导者给旧版追随者发日志,因为磁盘格式可能变了。

逻辑日志复制(Logical log replication):介于两者之间,记录行级别的变更------"插入了一行,值分别是......"。这种方式更灵活,支持不同版本共存,还能被外部系统解析做数据分析。

写在最后

单领导者复制就像一个有明确权力结构的团队:一个决策者说了算,其他人跟着学。优点是简单清晰、一致性有保障;缺点是决策者成了单点瓶颈,一旦挂了就得经历一波"权力交接"的惊险时刻。

但在分布式系统这个"职场"里,没有完美的制度,只有合适的权衡。单领导者复制已经被无数数据库证明是行之有效的方案,包括 PostgreSQL、MySQL、MongoDB、Kafka 等。

相关推荐
菜鸟小芯2 小时前
DAY2 从架构到落地:OpenClaw 核心能力全解析
架构
PD我是你的真爱粉2 小时前
RabbitMQ架构实战2️⃣:分布式事务下的跨服务数据同步
分布式·架构·rabbitmq
PD我是你的真爱粉2 小时前
RabbitMQ架构实战3️⃣:金融级交易流水对账系统
金融·架构·rabbitmq
前端不太难2 小时前
鸿蒙 App 架构重建后,为何再次失控
架构·状态模式·harmonyos
西京刀客2 小时前
openclaw架构原理-单进程应用 + 插件式扩展
ai·架构·oepnclaw
PD我是你的真爱粉2 小时前
RabbitMQ架构实战
python·架构·rabbitmq
阿里巴巴淘系技术团队官网博客11 小时前
从应用架构的视角看退小宝AI助手落地现状
人工智能·架构
星河耀银海11 小时前
Java安全开发实战:从代码防护到架构安全
java·安全·架构
桂花饼13 小时前
2026大模型新格局:智谱GLM-5发布,DSA+MoE架构如何破解落地痛点?
人工智能·架构·sora2·gemini 3·gpt-5.2·codex-max·glm-5