1. 生产环境副本集架构设计

MongoDB 副本集(Replica Set)是高可用部署的基础形态。它通过一组持有相同数据集的 mongod 实例,实现数据冗余、自动故障转移和读写分离。理解副本集的高可用原理、节点角色与选举机制,是规划生产架构的第一步。

副本集高可用原理

副本集由多个节点组成,其中一个节点被选举为主节点(Primary),其余节点为从节点(Secondary)。所有写操作都发送到主节点,主节点将操作记录到 oplog(操作日志),从节点持续拉取并重放 oplog,从而保持数据同步。当主节点不可用时,从节点通过选举产生新的主节点,集群在秒级内恢复写入能力。

副本集的高可用依赖两个关键机制:心跳检测和自动选举。节点之间默认每 2 秒发送一次心跳(heartbeat),若某节点在 10 秒内未响应,则被标记为不可达。当主节点不可达且多数节点确认后,触发选举流程。

MongoDB 副本集高可用架构(三节点 + 仲裁) 应用客户端 Driver / mongos Primary 主节点 读写操作入口 写入 oplog priority: 2 Secondary 从节点 1 拉取并重放 oplog 可承担读请求 priority: 1 Secondary 从节点 2 拉取并重放 oplog 可承担读请求 priority: 1 Arbiter 仲裁节点 不存数据 仅参与投票 priority: 0 写操作 读操作 oplog 同步 oplog 同步 心跳检测 选举机制: 主节点失联 → 多数节点确认 → 从节点发起选举 → 获得多数票(N/2+1)→ 新主节点产生 → 客户端自动重连

节点角色与职责

副本集中有三种节点角色:

  • Primary(主节点):唯一接收写操作的节点,所有写入先记录到本地 oplog,再由从节点异步复制。一个副本集在任意时刻最多只有一个主节点。
  • Secondary(从节点):持续从主节点同步 oplog 并重放,保持数据副本。从节点可以配置为可读,用于分担读请求,也可以配置为隐藏节点或延迟节点,用于特殊场景。
  • Arbiter(仲裁节点):不存储数据,仅参与选举投票,用于在节点数为偶数时打破投票僵局。仲裁节点资源消耗极低,但不能替代数据节点承担容灾职责。

生产环境中,通常建议使用三节点数据副本集(一主两从)或五节点数据副本集(一主四从)。三节点可容忍 1 个节点故障,五节点可容忍 2 个节点故障。若预算有限,也可采用“两数据节点 + 一仲裁节点”的方案,但该方案仅能容忍 1 个数据节点故障,且仲裁节点不提供数据冗余。

选举机制与多数派原则

MongoDB 副本集选举遵循多数派原则(Majority):新主节点必须获得超过半数投票节点的同意。投票节点包括所有具有投票权的副本集成员(数据节点和仲裁节点)。

例如,三节点副本集的多数派为 2,五节点副本集的多数派为 3。当主节点故障时,剩余的从节点会发起选举,获得多数票的节点成为新主节点。选举过程通常在数秒内完成,具体时间取决于 electionTimeoutMillis(默认 10000 毫秒)和心跳间隔。

节点的 priority 值影响选举优先级:priority 越高,越容易被选为主节点。生产环境中,通常将性能最强、网络最稳定的节点设置为较高 priority,确保其优先成为主节点。

根据业务读写比例规划节点数量

节点数量的规划需要综合考虑读写比例、容灾要求和成本预算。以下是几种典型场景的规划建议:

业务场景 读写比例 推荐节点数 容灾能力 说明
读多写少 10:1 以上 3 数据节点 + 1 仲裁 容忍 1 节点故障 从节点承担读请求,仲裁节点降低投票成本
读写均衡 约 1:1 3 数据节点 容忍 1 节点故障 标准三节点副本集,读写分离
写多读少 1:10 以下 3 数据节点 容忍 1 节点故障 写操作集中在主节点,从节点主要用于冗余
高容灾要求 任意 5 数据节点 容忍 2 节点故障 跨机房部署,多数派写入保障数据安全

节点分布与容灾规划

节点分布直接影响容灾能力。生产环境应遵循以下原则:

  1. 跨机架/跨可用区部署:将节点分散到不同的物理机架或云可用区,避免单点故障导致多数节点同时失效。
  2. 多数派节点同城:确保多数派节点位于同一低延迟网络内,避免跨地域网络抖动引发不必要的选举。
  3. 延迟节点用于容错:可配置一个延迟节点(secondaryDelaySecs),延迟数小时同步数据,用于误操作后的数据恢复。
  4. 隐藏节点用于备份:隐藏节点对客户端不可见,可专门用于备份或报表查询,不影响主节点性能。
规划建议:对于大多数生产业务,推荐采用“三数据节点 + 跨可用区部署”的方案。若业务对容灾要求极高(如金融、医疗),建议采用五节点副本集,并将节点分布到三个可用区(2+2+1 或 2+1+2),确保任意一个可用区故障时仍能保持多数派可用。

副本集配置示例

以下是一个三节点副本集的初始化配置示例(在 mongosh 中执行):

rs.initiate({
  _id: "rs0",
  members: [
    { _id: 0, host: "mongo-primary:27017", priority: 2 },
    { _id: 1, host: "mongo-secondary1:27017", priority: 1 },
    { _id: 2, host: "mongo-secondary2:27017", priority: 1 }
  ]
})

执行后,可通过 rs.status() 查看副本集状态,确认各节点角色和同步延迟。生产环境中,还应配置 writeConcern: { w: "majority" } 确保写入被多数节点确认后才返回成功,从而在故障切换时保证数据不丢失。

注意:副本集节点数量应为奇数(或使用仲裁节点使投票总数为奇数),以避免选举僵局。若使用偶数数据节点,必须添加仲裁节点,否则在故障场景下可能无法选出新主节点。