问题描述
MongoDB 4.4.9是PSS架构:
主库 10.20.17.51
从库 10.20.17.52
从库 10.20.17.53
现在要主库切换后,让从库10.20.17.52变成主库
1. 确认同步情况
1.1 从库查看
db.printSlaveReplicationInfo();
查看主从是否同步完成,等同步完成后才可以切换
wewint1:SECONDARY> rs.printSecondaryReplicationInfo()
source: 10.20.17.52:27017
syncedTo: Mon Sep 01 2025 10:34:22 GMT+0800 (CST)
-1 secs (0 hrs) behind the primary
source: 10.20.17.53:27017
syncedTo: Mon Sep 01 2025 10:34:20 GMT+0800 (CST) < 看时间戳是这个从库慢一点
1 secs (0 hrs) behind the primary
为什么会出现 -1 secs?
1)时间漂移(Clock Skew)
rs.printSecondaryReplicationInfo() 是通过比较 主节点与从节点的系统时间 和 oplog 时间戳 来计算延迟的。
如果主从节点系统时间不一致(即使只差 1 秒),就可能出现负值。
2)显示精度问题
当从库同步非常接近主库(<1秒),MongoDB 的计算逻辑可能显示为 -1,实际表示 “几乎同步”。
2. 方法1:修改优先级调整主从
通过 rs.status() 查看当前副本集状态,找到members需要切换为Primary节点的数组下标,
cfg.members[0] 中的 [0] 就是数组索引,表示第 1 个成员
wewint1:SECONDARY> rs.conf().members
[
{
"_id" : 0,
"host" : "10.20.17.51:27017",
"arbiterOnly" : false,
"buildIndexes" : true,
"hidden" : false,
"priority" : 10,
"tags" : {
},
"slaveDelay" : NumberLong(0),
"votes" : 1
},
{
"_id" : 1,
"host" : "10.20.17.52:27017",
"arbiterOnly" : false,
"buildIndexes" : true,
"hidden" : false,
"priority" : 5,
"tags" : {
},
"slaveDelay" : NumberLong(0),
"votes" : 1
},
{
"_id" : 3,
"host" : "10.20.17.53:27017",
"arbiterOnly" : false,
"buildIndexes" : true,
"hidden" : false,
"priority" : 3,
"tags" : {
},
"slaveDelay" : NumberLong(0),
"votes" : 1
}
]
将其优先级priority设置成members中最大的值,rs.conf()获取到当前配置,重新配置rs.reconfig(config)就修改成功了。
主库执行:
让从库10.20.17.52的优先级是高于其他两个节点的
PRIMARY> config = rs.conf()
PRIMARY> config.members[1].priority = 15
PRIMARY> rs.reconfig(config)
LOGS:
PRIMARY> rs.reconfig(config)
{
"ok" : 1,
"$clusterTime" : {
"clusterTime" : Timestamp(1756696295, 1),
"signature" : {
"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId" : NumberLong(0)
}
},
"operationTime" : Timestamp(1756696295, 1)
}
priority有效范围是 0–1000 的浮点数(含 0 和 1000),默认值 1。
说明:
mongodb中rs.reconfig(config)解释
底层调用的是 replSetReconfig 命令,只能在主节点上执行(除非加 {force:true})
1)对集群的影响
短暂不可写:主节点收到命令后,会先降级(step-down),触发一轮选举,期间所有写操作都会被拒绝;默认选举耗时 ≤12 s。
传播顺序:新配置先在主节点本地生效,再通过心跳推送到其它节点,只有当大多数投票节点都装上新配置后命令才返回成功。
一次只能改一个投票成员:从 4.4 开始,如果只是想添加/删除/改票,默认一次只能改 1 个投票成员,否则会报错;想批量改需 {force:true},但强制模式可能回滚已多数提交的写,生产慎用。
回滚风险:如果新配置把某些还没追上 oplog 的节点踢出投票组,可能导致旧主节点的已确认写被回滚。
2)版本差异
4.2 以前:主节点降级时会关闭全部客户端连接;4.2 起仅终止正在进行的写,不踢连接。
4.4 起:
– 默认等待多数投票节点安装新配置,最多可设 maxTimeMS 超时。
每次最多只允许1 个投票成员变动;如需一次改多个,必须 {force:true}。
- 5.0 起:
新增节点在达到 SECONDARY 状态前会被标记 newlyAdded: true,这段时间不算投票成员,防止误选举。
如果修改后的配置会改变隐式默认写关注,需要先显式 setDefaultRWConcern,否则 rs.reconfig() 失败。
确认当前主从状态
rs.status()
3. 方法2:手动触发主库降级(只有在优先级一样的情况下才会用)
登录 ADMIN 账号
mongo --host 10.20.17.51:27017 -u <replAdminUser> -p <password> --authenticationDatabase admin
PRIMARY> rs.stepDown(60)
LOGS:
{
"ok" : 1,
"$clusterTime" : {
"clusterTime" : Timestamp(1756697187, 1),
"signature" : {
"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId" : NumberLong(0)
}
},
"operationTime" : Timestamp(1756697187, 1)
}
说明:
1)60秒是必须的吗?
rs.stepDown(60) 中的 60 是“强制冷却”秒数。
在这段时间内,当前节点不会再次竞选主库,让其他有资格节点有充足时间完成选举并稳定成为新主库。
最小允许值为 5 秒。可以改为30秒吗?可以但是没必要。rs.stepDown(30),只要集群网络、节点状态都正常,30 秒通常足够完成选举。
2) 选举的顺序
主库 10.20.17.51 执行 rs.stepDown(60)降低后,是不是从库优先级高的变成主库呢?
priority = 0:永远没有资格成为主库(只能当从库)
priority > 0:都有同等机会被选举为主库,不是“谁高谁上”。
当主库 rs.stepDown() 或宕机后,剩余节点会触发选举,投票规则如下:
1)最新 optime(同步数据最新的节点)优先
如果 10.20.17.52 的 oplog 比 10.20.17.53 更新,它就更容易被选举为主库。
rs.printSecondaryReplicationInfo()
2)优先级只是“参与资格”
只要 priority > 0,就都可以被选,不是优先级高的就一定赢。
3)“多数派”投票
需要获得大多数存活节点的投票才能当选主库