MongoDB副本集从节点宕机时如何保障API持续正常运行
根本原因
你遇到的问题是MongoDB副本集选举规则导致的:副本集选主需要获得超过半数投票节点的支持,1主1从的架构总共有2个投票节点,半数阈值为1,超过半数就需要至少2票。当从节点宕机后,仅剩的主节点只能拿到1票,达不到选主要求,会自动降级为SECONDARY节点,集群无可用主节点,无法处理写请求,所以API无法正常启动运行。
解决方案
1. 长期高可用方案:调整副本集节点组成(推荐)
这是从架构层面解决问题的最优方案:
- 新增1个MongoDB仲裁节点(Arbiter),仲裁节点不存储业务数据、仅参与选举投票,资源占用极低。调整后副本集总共有3个投票节点,半数阈值为1.5,超过半数需要至少2票,任意1个节点宕机后剩下2个节点可以正常选举主节点,原主节点不会降级。
- 仲裁节点部署完成后执行以下命令加入副本集:
rs.addArb("arbiter-node-ip:27017")
- 也可以选择新增1个数据节点,组成1主2从的3数据节点副本集架构,可靠性更高。
2. 临时运维方案:手动调整副本集配置
如果暂时无法新增节点,需要临时停从节点做运维,可以提前修改副本集配置,取消从节点的投票权,避免主节点降级:
// 获取当前副本集配置 cfg = rs.conf() // 假设从节点是members数组的第2项,索引为1,将其投票权和优先级设为0 cfg.members[1].votes = 0 cfg.members[1].priority = 0 // 应用新配置 rs.reconfig(cfg)
运维完成恢复从节点后,记得改回原有配置,避免后续主节点宕机时无法正常切换。
3. 优化Mongoose连接配置
调整Mongoose连接参数,适配副本集高可用场景:
- 连接串必须指定所有节点地址、副本集名称,开启重试写、节点自动发现等配置,示例:
const mongoose = require('mongoose') mongoose.connect('mongodb://primary-ip:27017,secondary-ip:27017/your-db-name?replicaSet=你的副本集名称&readPreference=primaryPreferred&retryWrites=true&connectTimeoutMS=30000&socketTimeoutMS=30000')
readPreference=primaryPreferred表示优先读主节点,主节点不可用时可以临时读从节点,进一步提升可用性。- 可以配合添加Mongoose全局错误捕获逻辑,对可重试的操作添加自动重试机制。
内容的提问来源于stack exchange,提问作者Chicky
相关产品推荐
相关产品推荐

