新节点加入后卡在startup或startup2状态,说明正在进行initial sync而非失败;常见原因包括服务未启动、端口被拦截、主机名无法解析或数据目录非空;应确认连通性、主节点身份、replsetname一致、清空dbpath并使用可解析主机名。

rs.add() 执行后节点状态一直是 STARTUP 或 STARTUP2
新节点加入后卡在 STARTUP 状态,说明它还没完成初始化同步(initial sync),不是失败,而是正在拉取全量数据。常见原因有:目标节点的 mongod 进程未启动、端口被防火墙拦截、副本集配置中指定的主机名无法从其他成员解析(比如用了 localhost 或内网 IP 但 DNS 不通)、或者新节点的数据目录非空且含有不兼容的旧数据。
实操建议:
- 先在新节点上执行
mongo --host <new-node-ip>:27017</new-node-ip>确认服务可连通; - 在已有主节点上运行
rs.status(),检查members[n].stateStr和members[n].health; - 确保所有节点使用一致的
replSetName(查看启动参数或mongod.conf中的replication.replSetName); - 若新节点已有数据,清空其
dbPath目录(除非你明确要做增量加入且已预同步); - 添加时用可被所有成员解析的主机名(如
"node3.example.com:27017"),别用"localhost:27017"。
rs.add() 报错 “Quorum check failed” 或 “Not master”
这类错误通常发生在你没在当前主节点上执行 rs.add()。副本集配置变更必须由主节点发起,如果连接的是从节点,命令会直接拒绝。
实操建议:
- 先运行
rs.isMaster().ismaster确认当前连接的是主节点; - 如果返回
false,用rs.status()找出stateStr: "PRIMARY"的成员,重新mongo连过去再操作; - 避免在配置过程中手动 kill 主节点或触发强制降级,否则可能造成短暂无主,导致
rs.add()失败; - 如果集群刚初始化完,主节点选举尚未完成(
rs.status()显示多数成员是STARTUP2),请等待 10–30 秒再试。
添加节点后写入性能明显下降
新增节点触发了全量 initial sync,期间主节点要持续压缩 oplog 并传输历史数据,同时还要服务正常读写,I/O 和网络带宽压力陡增。尤其当新节点磁盘慢、网络延迟高,或 oplog 太小(默认 5% 的 dbPath 空间,但至少 1GB)时,容易拖垮主节点。
实操建议:
- 添加前确认主节点 oplog 足够大:运行
rs.printReplicationInfo(),看oldest timestamp是否比预估同步时间早; - 给新节点分配 SSD 存储,并关闭其 journal(仅限临时加速 initial sync,同步完成后务必重启启用);
- 避免在业务高峰添加节点;
- 监控
rs.status().members[n].optimeDate,与主节点对比,判断同步进度是否停滞(长时间无变化需查日志)。
rs.add() 后节点始终不进入 SECONDARY 状态
成功同步完数据后,节点应自动进入 SECONDARY,但如果卡在 RECOVERING 或反复切换 STARTUP2/RECOVERING,大概率是 oplog 追不上主节点——要么主节点写入太快,要么新节点磁盘太慢,要么网络丢包严重。
实操建议:
- 检查新节点
/var/log/mongodb/mongod.log,搜索"not enough data in oplog"或"oplog gap"; - 临时降低主节点写入压力(如暂停批量导入),观察状态是否推进;
- 确认新节点系统时间与其他成员一致(误差 > 1s 可能引发认证或心跳异常);
- 如果多次失败,考虑用物理备份(
mongodump+mongorestore)预填充数据,再以空 oplog 启动,减少 initial sync 时间。
真正麻烦的不是加节点这个动作,而是 initial sync 过程中主节点和网络的隐性负载。很多人只盯着 rs.add() 成功就以为万事大吉,结果半小时后发现主节点 CPU 暴涨、慢查询激增——那其实是同步在后台闷声干活。盯住 rs.status() 里每个成员的 optimeDate 和日志里的 InitialSync 行,比反复敲命令有用得多。











