1. 生产环境副本集架构设计
MongoDB 副本集(Replica Set)是高可用部署的基础形态。它通过一组持有相同数据集的 mongod 实例,实现数据冗余、自动故障转移和读写分离。理解副本集的高可用原理、节点角色与选举机制,是规划生产架构的第一步。
副本集高可用原理
副本集由多个节点组成,其中一个节点被选举为主节点(Primary),其余节点为从节点(Secondary)。所有写操作都发送到主节点,主节点将操作记录到 oplog(操作日志),从节点持续拉取并重放 oplog,从而保持数据同步。当主节点不可用时,从节点通过选举产生新的主节点,集群在秒级内恢复写入能力。
副本集的高可用依赖两个关键机制:心跳检测和自动选举。节点之间默认每 2 秒发送一次心跳(heartbeat),若某节点在 10 秒内未响应,则被标记为不可达。当主节点不可达且多数节点确认后,触发选举流程。
节点角色与职责
副本集中有三种节点角色:
- 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 节点故障 | 跨机房部署,多数派写入保障数据安全 |
节点分布与容灾规划
节点分布直接影响容灾能力。生产环境应遵循以下原则:
- 跨机架/跨可用区部署:将节点分散到不同的物理机架或云可用区,避免单点故障导致多数节点同时失效。
- 多数派节点同城:确保多数派节点位于同一低延迟网络内,避免跨地域网络抖动引发不必要的选举。
- 延迟节点用于容错:可配置一个延迟节点(
secondaryDelaySecs),延迟数小时同步数据,用于误操作后的数据恢复。 - 隐藏节点用于备份:隐藏节点对客户端不可见,可专门用于备份或报表查询,不影响主节点性能。
副本集配置示例
以下是一个三节点副本集的初始化配置示例(在 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" } 确保写入被多数节点确认后才返回成功,从而在故障切换时保证数据不丢失。