MongoDB 复制集是什么?主从选举和故障恢复怎么做?
简化版
MongoDB 复制集是一组维护相同数据集的节点,通常包含一个 primary 和多个 secondary。写请求默认进入 primary,secondary 复制 primary 的 oplog 来同步数据。primary 故障时,复制集会自动选举新的 primary,从而提升高可用能力。
详细版
复制集核心概念:
- Primary:接收写入的主节点;
- Secondary:复制数据的从节点,可用于读扩展或容灾;
- Oplog:记录数据变更的操作日志;
- Election:主节点不可用时选举新主;
- Majority:多数派,影响写入确认和选举安全;
- Read Preference:控制读从哪里读;
- Write Concern:控制写入确认级别。
复制集解决的是高可用和数据冗余,但异步复制可能带来复制延迟。读 secondary 时要注意读到旧数据的风险。
完整版教学
一、复制集为什么存在
单节点 MongoDB 一旦宕机,服务不可用,数据也只有一份。复制集通过多节点保存数据副本,提高容灾能力。
典型结构:
Primary
├── Secondary
└── Secondary
业务写 primary,secondary 持续复制。
二、Oplog 是复制的关键
Primary 上的数据变化会记录到 oplog。Secondary 拉取并重放这些操作,让自己追上 primary。
这和直接拷贝整库不同。复制集持续同步增量变化,适合在线高可用。
但 oplog 是有大小窗口的。如果 secondary 落后太久,旧 oplog 被覆盖,就可能需要重新同步。
三、故障时如何选举新主
当 primary 不可用时,复制集成员会发起选举。获得多数派支持的 eligible secondary 可以成为新的 primary。
多数派机制很重要,它避免网络分区时出现多个主节点同时写入。
如果节点数太少,比如只有两个节点,故障时可能无法形成多数派。生产环境常见至少三个投票成员。
四、读写路径要理解清楚
默认写入 primary。读取默认也通常从 primary 读,这样更容易读到最新数据。
如果配置读 secondary,可以分担读压力,但要接受复制延迟:
Primary 已写入
Secondary 还没同步
此时从 secondary 读可能看到旧数据。对强一致读要求高的业务要谨慎。
五、Write Concern 影响写入安全
写关注决定写入要被多少节点确认才算成功。比如 majority 表示多数节点确认。
更高的写关注提高数据安全性,但会增加写入延迟。低写关注延迟低,但故障时可能丢失尚未复制的数据。
这就是一致性、性能和可用性之间的权衡。
六、复制集也有延迟和回滚边界
复制集提高高可用,但不等于每个节点时时刻刻完全一致。Secondary 通过 oplog 异步追赶 primary,如果复制延迟是 2 秒,从 secondary 读就可能看到 2 秒前的数据。故障切换时,未被多数节点确认的写入也可能在新主选出后被回滚。
| 风险 | 产生原因 | 常见控制 |
|---|---|---|
| 复制延迟 | secondary 重放 oplog 落后 | 监控 lag,关键读走 primary |
| oplog 窗口不足 | 落后太久,旧 oplog 被覆盖 | 调大 oplog,及时修复落后节点 |
| 写入回滚 | 旧 primary 上未多数确认写入 | 使用 w: majority |
| 无法选主 | 投票节点不足多数派 | 至少 3 个投票成员 |
例如 3 节点复制集里,写入只达到 primary 就返回成功,primary 立刻宕机且该操作没复制到另外两个节点,新主选出后可能没有这次写入。若使用 writeConcern: majority,这种风险会明显降低,但写入延迟会上升。
七、常见误区与追问
Primary 写入 -> oplog -> Secondary 拉取 -> 重放 -> 数据追平
记忆钩子:复制集解决“节点挂了还能服务”,但 secondary 读新鲜度和写入安全要看复制延迟与 write concern。
- 误区:有复制集就不会丢任何写入。 如果写入未被多数节点确认,primary 故障后仍有回滚风险。
- 误区:secondary 读一定和 primary 一样新。 复制是异步追赶,secondary 可能存在毫秒到秒级甚至更长延迟。
- 误区:两个节点复制集就足够高可用。 两节点故障时容易无法形成多数派,生产通常至少 3 个投票成员。
- 追问:oplog 有什么作用? 它记录 primary 上的数据变更,secondary 通过拉取和重放 oplog 同步数据。
- 追问:为什么需要多数派选举? 多数派能避免网络分区下多个节点都认为自己是主,从而减少脑裂写入风险。
- 追问:读扩展怎么做更稳? 非关键读可以按 read preference 走 secondary,写后读和强一致读优先走 primary,并监控复制延迟。
八、加强记忆
MongoDB 复制集记住“一主多副本、oplog 同步、故障选主、多数派保护”。它解决高可用和冗余,但 secondary 读可能有延迟;写安全看 write concern,读路径看 read preference。