是什么
rs.add() 与 rs.remove() 是 mongosh 中修改复制集成员配置的辅助方法,底层等价于 rs.reconfig():把变更写进复制集配置文档,多数投票成员确认后配置版本号递增。新加入的成员默认是普通投票成员,进程启动后会做初始同步,把主节点现有数据全量复制过来,所以扩容不是立刻可用,必须盯着同步进度直到它变成 SECONDARY。
基本信息
| 适用版本 | MongoDB 3.0+,在 mongosh / 旧 mongo shell 中执行 |
|---|---|
| 执行位置 | 必须连到当前主节点(PRIMARY),从节点上执行会直接报错 |
| 两种写法 | rs.add(host) 或 rs.add({ host, priority, votes, hidden, tags, secondaryDelaySecs }) |
| 移除写法 | rs.remove(host),host 字符串必须与 rs.conf() 里的 host 完全一致 |
| 核对命令 | rs.status()、rs.conf().members、rs.conf().version |
典型使用场景
- 扩容读能力:加入 priority 0、votes 0 的只读成员,专门承接报表查询与备份任务,不干扰选举
- 故障替换:先把坏节点 rs.remove,再把新机器用完全相同的 host 名称加入,客户端连接串不用改
- 跨机房部署:给成员打 tags,配合读偏好把读请求固定在某个机房,减少跨机房时延
- 延迟节点:设置 secondaryDelaySecs 保留一份滞后数据,用于误删、误更新后的快速捞回
- 隐藏节点:hidden 且 priority 0 的成员不参与选举、对客户端不可见,适合离线分析
扩容与缩容
扩容与缩容
rs.status().members.map(m => m.name) # 先确认当前成员清单
rs.add({ host: "m4:27017", priority: 0, votes: 0 }) # 只读节点,不参与投票
rs.add("m5:27017") # 默认成员,参与投票
rs.conf().version # 配置版本号,每次变更 +1
rs.status().members.filter(m => m.stateStr === "STARTUP2").length # 看是否还在初始同步
rs.remove("m4:27017") # 移除,host 写法必须一致成员状态读法
| stateStr | 含义 | 处理动作 |
|---|---|---|
| STARTUP2 | 初始同步进行中,尚未追平 | 等待即可,期间别再加压 |
| SECONDARY | 同步正常,可提供读 | 无需处理 |
| RECOVERING | 追赶中、回滚中或落后过多 | 先看复制延迟与 oplog 窗口 |
| ARBITER | 仲裁节点,不存业务数据 | 不要在仲裁节点上读数据 |
| REMOVED | 已被移出配置,进程仍可能活着 | 确认是否要停掉对应进程 |
移除成员前必须确认剩余投票成员仍能构成多数:三节点复制集一次只能移除一个,连续删两个会让复制集失去多数而转入只读,此时只能恢复数据文件或重新初始化才能写入。
大库初始同步非常重,磁盘 IO 与网络会长时间打满。可以在加入前先摆好数据目录再启动以跳过全量同步,也可以用 rs.syncFrom() 指定同步源,避免多个新节点同时压向主节点。