← 返回分布式系统
📡 分布式存储 · 面试高频

数据复制

复制(Replication)= 把同一份数据存到多台机器。它是高可用、读扩展、就近访问的基石,但也带来了"主从/多主/无主"和"同步/异步"的选择题。

🎯 一、为什么需要复制

高可用
一台挂了,副本顶上,系统不中断。
读扩展
多个副本分担读流量(一写多读)。
就近低延迟
副本放在离用户近的机房/地域。
备份容灾
天然多份拷贝,抗单点数据丢失。

🕸️ 二、三种复制拓扑

① 单主(主从) 主 从 从 ② 多主(多写) 主A 主B ③ 无主(Dynamo)
拓扑写入一致性优点缺点代表
单主(主从)仅主可写较强简单、无写冲突主是瓶颈/单点MySQL 主从、Redis
多主多节点可写需解决冲突就近写、容错好写冲突/脑裂MySQL MGR、Cassandra
无主任意节点可写最终一致极高可用、易扩展读需协调/可能脏读DynamoDB、Cassandra

🔁 三、同步 vs 异步复制

同步复制(Synchronous)
主库等所有副本都确认写入才返回成功。优点:不丢数据、强一致;缺点:任一副本慢/挂都阻塞写入,可用性差。常用于金融核心(至少 1 个同步副本)。
异步复制(Asynchronous)
主库写入本地即返回,副本"稍后"追。优点:写入快、可用高;缺点:主挂可能丢未同步数据,副本读到旧值。绝大多数互联网系统默认选它。
半同步(折中)
主库等"至少 1 个/部分"副本确认即可,兼顾性能与安全性(MySQL 半同步、Raft 的多数派)。

⏳ 四、异步复制的"延迟"陷阱

异步复制下,副本落后于主库是常态。这会引出三个经典一致性异常,面试必考。

① 读己之写(Read-Your-Writes)
用户刚改完自己的头像,刷新却看到旧的——因为读到了还没追上来的副本。解法:写后一段时间/关键读走主库,或用"sticky session"把同一用户路由到含最新数据的副本。
② 单调读(Monotonic Reads)
用户连续刷新,数据却"时光倒流"(先看到新值再看到旧值)——因为两次读打到了不同进度的副本。解法:按用户固定路由到同一副本。
③ 一致前缀读(Consistent Prefix)
先发生的事件比后发生的事件更晚被看到(如问答中先看到"回答"才看到"提问")。解法:按因果关系(因果序列)路由相关数据的读。
💡
这三类问题都属于"最终一致性"下的用户体验问题,靠"会话/因果/用户级路由"缓解,而非强一致。

🧭 五、怎么选型

🧭
经验法则:① 写少读多、要简单 → 单主;② 多地域写、容忍冲突 → 多主/无主;③ 要强一致且高可用 → 用 Raft/Paxos 类共识(见共识目录)做复制;④ 极致可用、能接受最终一致 → 无主。

🎯 六、面试高频追问

主从复制下主库挂了怎么办?
触发故障转移(failover):选一个从库提升为新主(需先追平数据),更新路由。难点:脑裂(旧主复活)、数据丢失(异步未同步部分)。生产靠 Orchestrator/MHA/共识选主。
主从延迟怎么监控和治理?
监控 Seconds_Behind_Master / 复制位点差;治理:并行复制、降低大事务、读分流策略、业务上接受最终一致。
复制和分片是什么关系?
正交但可以叠加:分片解决"数据量/算力"(水平切),复制解决"高可用/读扩展"(多副本)。一个分片内部通常又是一主多从。

延伸阅读:一致性哈希 · 数据分片 · CAP 理论