主备复制
主备复制由主节点确定写入顺序,并把已排序的状态变化复制给备节点,以支持数据冗余、读取扩展和故障切换。
1. 主节点负责确定写入顺序
在一个复制组中,客户端通常把写请求交给主节点。主节点为请求确定日志位置或版本,再把记录发送给备节点。备节点按相同顺序应用确定性状态变化,才能得到与主节点一致的结果。
系统需要明确四件事:
- 哪个节点有权接受写入。
- 一条写入在什么条件下向客户端确认成功。
- 备节点落后时怎样追赶。
- 主节点故障后怎样选择新主并阻止旧主继续写入。
MySQL、Redis 和共识系统都可能出现主节点与副本角色,但复制日志、确认语义和切换协议并不相同,不能只凭“主备”名称推断一致性。
2. 写入确认条件决定数据风险
主节点可以在不同阶段确认请求:
- 本地确认:主节点本地记录后返回,延迟低;主节点永久故障时,未复制数据可能丢失。
- 一个或多个备节点确认:降低单机故障丢失窗口,但仍要定义备节点确认的是收到、写入内存还是持久化。
- 多数派提交:共识系统通常在当前任期日志被多数派持久保存后提交,能够支持安全领导权切换。
等待所有副本会让最慢或故障副本限制可用性。选择确认条件时,要把允许的数据丢失、写入延迟、故障域和恢复目标写清楚。
3. 日志复制处理持续增量
主节点把写入表示为有顺序的日志项,备节点按相同顺序应用:

复制状态机还要求操作是确定性的,或者把时间、随机数和外部结果一并写入日志。仅记录“重新计算折扣”这类依赖外部状态的命令,可能让不同副本得到不同结果。
日志包含索引、任期或版本,备节点据此检测缺口和冲突。收到重复日志时应安全忽略或覆盖未提交分支,已经提交的前缀不能在合法的新主上消失。
4. 快照用于初始化和压缩历史
新备节点如果从系统创建时的第一条日志开始重放,恢复时间会随历史不断增长。系统会周期性生成某个日志位置上的状态快照:

备节点先安装快照,再重放快照之后的增量日志。生成快照时要得到一致状态,并记录其对应日志位置;复制期间主节点仍可能产生新日志,所以快照和增量追赶需要衔接。
状态转移与日志复制是互补机制。它们不能分别直接等同于“最终一致性”和“强一致性”,也不等于半同步复制;一致性取决于提交规则、读取规则与故障切换协议。
5. 故障切换需要新的领导权证明
节点无法仅凭“联系不上主节点”就宣布自己为新主,因为网络分区可能让旧主仍在服务。安全切换通常需要:
- 多数派选举或外部仲裁,确保同一任期只有一个领导者。
- 单调递增的任期、epoch 或 fencing token,让存储和下游拒绝旧主写入。
- 候选节点拥有足够新的已提交日志,避免丢失已经确认的数据。
- 客户端发现新主,并停止向旧地址发送写入。
只有健康检查和 VIP 漂移,无法独立解决双主与数据分叉。
6. 备节点落后会影响读取与恢复
备节点可能因为网络、磁盘或应用速度落后于主节点。使用备节点提供读取时,要说明允许的复制延迟:
- 普通展示可以读取稍旧数据。
- 写后立即读可以固定主节点、携带已提交版本,或等待副本追到指定位置。
- 权限、余额和所有权判断通常不应从无法确认新鲜度的副本读取。
监控至少包含复制位置差、时间延迟、日志积压、快照安装进度和预计追平时间。备节点长期无法追平时,继续保留它会拖累磁盘与网络,也会延长切换风险窗口。
7. 恢复需要验证数据和业务语义
故障切换完成后,应检查:
- 新主的提交位置是否包含切换前已确认数据。
- 旧主重新加入前是否被隔离并删除冲突的未提交分支。
- 客户端是否仍有连接或 DNS 缓存指向旧主。
- 消息、缓存和下游派生数据是否需要重放或对账。
- 复制延迟、错误率和业务成功率是否恢复到目标。
定期演练主节点故障、网络分区和慢副本,才能验证恢复时间与数据丢失目标。
8. 常见问题
8.1 有两个副本就不会丢数据吗
不能保证。写入如果只在主节点本地确认,复制前主节点永久故障仍可能丢失。即使备节点收到数据,也要明确是否持久化、能否被选为新主,以及确认后的日志是否会在选举中保留。
8.2 备节点可以直接承担所有读取吗
取决于新鲜度要求。异步副本可能返回旧值,写后读、权限和余额等流程要使用主节点、版本等待或具备线性读取保证的协议。
9. 面试题
9.1 主节点故障后,怎样保证新主不丢失已提交数据并避免双主
出现公司:字节跳动
考察重点
- 写入确认、日志提交与副本追赶。
- 多数派选举、任期和 fencing。
- 快照、故障恢复和数据验证。
相关内容:第 1 节“主节点负责确定写入顺序”至第 7 节“恢复需要验证数据和业务语义”。
参考回答
先定义提交:共识复制通常要求当前任期的日志被多数派持久保存后才向客户端确认。选举时只有获得多数派投票、并且日志至少和投票者一样新的节点才能成为新主,这使两个分区无法同时获得有效多数派,也让已提交前缀保留在合法候选者中。
每次领导权使用递增任期或 fencing token,下游拒绝旧任期写入,避免旧主在网络恢复后继续修改。新备节点通过快照加后续日志追赶,旧主重新加入前截断未提交冲突。切换后还要核对提交位置、旧连接、复制延迟和业务数据,并通过故障演练验证 RTO 与允许的数据丢失范围。异步主从若不使用这些规则,就必须明确可能丢失最近已确认写入。