你现在的情况是:三台机器上都执行了 rs.initiate(),这会导致每台机器都独立地成为了自己的单节点副本集
(各自成为一个不同的副本集),它们彼此之间并不知道对方的存在,所以整个副本集无法形成。
🔥 问题本质
MongoDB 的副本集只能由一个节点执行一次 rs.initiate() 来初始化整个副本集。
你在三台机器上都执行了,相当于创建了三个互不相关的副本集,这是错误的操作。
✅ 正确做法(修复步骤)
✅ 步骤 1:停止所有节点上的 MongoDB 服务
清理数据目录(dbpath)
bash
复制
1 2 3 4
| # 每台机器上执行 sudo systemctl stop mongod # 或 mongod --shutdown --dbpath /data/db
|
✅ 步骤 2:清理副本集配置(每台机器都要做)
MongoDB 会把副本集配置保存在 local.replset 集合中,你需要清理掉这些配置。
bash
复制
1 2 3 4 5 6 7 8 9 10
| # 进入 MongoDB shell(单节点启动,不指定 replSet) mongod --dbpath /data/db --port 27017 --fork --logpath /var/log/mongod.log
mongo --port 27017
# 删除副本集配置 use local db.dropDatabase() # 会清空 local 库,包括副本集配置和 oplog
exit
|
⚠️ 注意:这个操作会清除副本集配置和 oplog,不会影响你的业务数据(除非你业务数据也放在 local 库)。
✅ 步骤 3:重新以副本集模式启动 MongoDB(所有节点)
bash
复制
1
| mongod --replSet rs0 --bind_ip 0.0.0.0 --dbpath /data/db --port 27017 --fork --logpath /var/log/mongod.log
|
✅ 步骤 4:只在一个节点(主节点)上执行初始化
连接任意一台节点(建议选你希望的 PRIMARY),执行:
JavaScript
复制
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| rs.initiate({ _id: "rs0", members: [ {_id: 0, host: "192.168.0.245:27017"}, {_id: 1, host: "192.168.0.246:27017"}, {_id: 2, host: "192.168.0.247:27017", arbiterOnly: true} ] })
rs.initiate({ _id: "replicaset", members: [ {_id: 0, host: "192.168.0.245:27017"}, {_id: 1, host: "192.168.0.246:27017"}, {_id: 2, host: "192.168.0.247:27017", arbiterOnly: true} ] })
|
| 字段 |
含义 |
_id: "replicaset" |
创建或指定一个名为 replicaset 的副本集。 |
members |
列出这个副本集里的所有成员(节点)。 |
_id: 0/1/2 |
每个成员在副本集内的唯一标识符。 |
host |
每个成员的 IP:端口,告诉副本集怎么找到它们。 |
- 当前你连接的这台节点(假设是 192.168.0.245)会成为 PRIMARY。
- 它会尝试与 192.168.0.246、192.168.0.247 建立心跳连接。
- 如果这两台节点已经以
--replSet replicaset 启动且数据目录干净,它们会进入 SECONDARY 状态。
- 最终形成一个 三节点副本集(1 主 2 从)。
✅ 步骤 5:验证副本集状态
JavaScript
复制
✅ 总结一句话
每台都执行 rs.initiate() 是错误的,必须清理配置后,只用一台机器初始化整个副本集。
如你不确定该删哪个目录、如何备份,我可以帮你写个脚本。