必须带replicaSet参数,否则驱动不启用副本集逻辑;推荐写法为mongodb://host1:27017,host2:27018,host3:27019/mydb?replicaSet=rs0,仅单节点加replicaSet无法故障转移。

直接用 mongodb 官方驱动(v6+)连接副本集,比 mongoose 更可控、更少隐式行为;连接字符串里必须带 replicaSet 参数,否则驱动不会启用副本集发现逻辑,会退化为单节点连接。
连接字符串必须包含 replicaSet 和完整节点列表
驱动靠这个参数判断“这是副本集”,并启动自动拓扑发现和故障转移。只写一个地址 + replicaSet 也能连,但节点宕机时无法自动切换 —— 驱动需要至少两个地址才能做成员健康检测。
- ✅ 正确写法(推荐):
mongodb://host1:27017,host2:27018,host3:27019/mydb?replicaSet=rs0 - ❌ 错误写法(看似能连,实则无故障转移):
mongodb://host1:27017/mydb?replicaSet=rs0—— 驱动不会去查其他成员 - ⚠️ 注意:节点顺序无关,驱动会自己探测主从角色;但 DNS 解析失败的地址会导致连接延迟,建议提前验证所有 host 可达
readPreference 不是性能银弹,选错会读到脏数据
默认 primary 是最安全的,secondaryPreferred 在主挂了时能降级读,但 secondary 或 nearest 有明确风险:
- 副本集同步是异步的,
secondary节点可能落后主节点几百毫秒甚至几秒,写完立刻读可能读不到 - 多个
secondary节点延迟不同,同一查询在不同请求中可能返回不一致结果(非单调读) - 如果业务要求强一致性(如订单状态、余额),别设
readPreference=secondary,哪怕加了readConcern=majority也解决不了延迟问题 - 真要分摊读压力,优先考虑分片,不是靠读从节点
连接池配置不当会导致连接数爆炸
副本集里每个节点都维护独立连接池。默认 maxPoolSize=100,三节点副本集 + readPreference=secondaryPreferred,理论上最多打开 3 × 100 + 6(监控连接)= 306 个 socket —— 很容易触发系统文件描述符限制或 MongoDB 的 maxIncomingConnections 拒绝。
- 生产环境建议显式设
maxPoolSize: 20~50,根据实际并发量调 - 设
minPoolSize要谨慎:设为5意味着空闲时也保持 15 个 socket(3 节点 × 5),对小流量服务反而浪费 - 如果应用只读主节点(默认行为),其实只需关心主节点的连接池,从节点池基本闲置
认证和 TLS 必须在 URI 里声明,不能靠选项补
authSource、tls=true 这类参数必须出现在连接字符串末尾,写在 MongoClient 的 options 对象里会被忽略。
- ✅ 正确:
mongodb://user:pass@h1:27017,h2:27018/hello?replicaSet=rs0&authSource=admin&tls=true - ❌ 无效:
new MongoClient(uri, { tls: true })—— 驱动不认这个字段,TLS 不会启用 - 特别注意 Atlas 用户:URI 里已含
tls=true和retryWrites=true,不要手动覆盖;本地自建副本集若启了 TLS,漏掉tls=true会卡在 handshake 阶段,日志只报connect ECONNREFUSED,不提示 TLS 问题
副本集连接真正的难点不在“连上”,而在“连得稳、读得准、扩得开”——节点发现、读偏好语义、连接池膨胀、TLS/认证耦合,这四点任意一个配错,都会在高负载或故障时暴露,且错误现象模糊(比如偶发超时、数据不一致),调试成本远高于初始配置时间。











