MongoDB主从切换实战:如何让指定从库“精准”升级为主库?保姆级教程!

发布于:2025-09-02 ⋅ 阅读:(24) ⋅ 点赞:(0)

问题描述

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)“多数派”投票

需要获得大多数存活节点的投票才能当选主库


网站公告

今日签到

点亮在社区的每一天
去签到