接上一篇文章《Mongodb只读副本集如何切换到读写模式》,大概思想就是如何强制把副本集中仅存secondary节点提升为主,主要是通过standalone方式重启实例来实现,经过与大家交流与沟通,虽然此方式可以实现,但是以前老节点必须重新初始化,尤其当单节点数据很大时,此方式是缺点明显.最有效方式是通过rs.reconfig()方式来实现.此方式也分为2种:
1、使用rs.reconfig重新配置仅有一个节点的副本集,如异常节点恢复后,可以手动加入副本集(在oplog窗口内,如果超过恢复窗口,也需要全量出重新初始化)
2、使用rs.reconfig重新配置副本集,将异常节点优先级与投票都设置为0,从而保持副本集成员不变的情况下快速恢复业务,如异常节点恢复后可以自动重新加入副本集(在oplog窗口内,如果超过恢复窗口,也需要全量出重新初始化)
针对方式1与方式2差别不大,本次采用方式2来简单重现过程.
【注意事项】
如果原来应用配置writeConcern:majority模式,此时写入的数据也可能会出现丢失(此secondary存在延迟,导致数据没有同步或者回滚(原主节点重新加入)
【将异常节点优先级与投票都设置为0来恢复副本集】
1、检查当前副本集情况
备注:此时只有10.130.9.149:37017实例是正常的
代码语言:javascript复制xiaoxu:SECONDARY> rs.status();
{
"set" : "xiaoxu",
"members" : [
{
"_id" : 0,
"name" : "10.130.9.149:37017",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY"
},
{
"_id" : 1,
"name" : "10.130.10.149:37017",
"health" : 0,
"state" : 8,
"stateStr" : "(not reachable/healthy)"
},
{
"_id" : 2,
"name" : "10.130.10.150:37017",
"health" : 0,
"state" : 8,
"stateStr" : "(not reachable/healthy)"
}
],
"ok" : 1
}
2、修改异常实例优先级别与投票节点
代码语言:javascript复制xiaoxu:SECONDARY> config=rs.config();
xiaoxu:SECONDARY> config.members[1].priority=0
0
xiaoxu:SECONDARY> config.members[1].votes=0
0
xiaoxu:SECONDARY> config.members[2].votes=0
0
xiaoxu:SECONDARY> config.members[2].priority=0
3、重新配置副本集
备注:此时是备库,无法直接运行,必须加force方式,副本集中多数节点是指的投票节点个数,例如PSS,如果SS都votes都等于0,,那么此时多节点就是主库,也就是1.PSA架构,A虽然可以具有投票为1且不能修改,如果此时S挂了,投票节点是多数节点,但writeconcern无法满足多节点写入,从3.6版本开始,read concern同样无法majority.
代码语言:javascript复制xiaoxu:SECONDARY> rs.reconfig(config);
{
"ok" : 0,
"errmsg" : "replSetReconfig should only be run on PRIMARY,
but my state is SECONDARY; use the "force" argument to override",
"code" : 10107,
"codeName" : "NotMaster"
}
xiaoxu:SECONDARY> rs.reconfig(config,{force:true});
{ "ok" : 1 }
xiaoxu:SECONDARY> 等几秒钟secondary会变成primary
xiaoxu:PRIMARY> rs.status();
4、再次验证副本集状态
备注:虽然其他节点都是not reachable/healthy,但副本集此时可以提供读写业务.虽然可以提供写业务,建议生产环境最低配是PSA(存在一系列问题,所以最好不要配置PSA架构),最近遇到类似PSS(延迟)A架构,经常出现cache used超过95%导致宕机经过去掉A以后且把延迟节点延迟改小,内存使用基本保持在80%以下,也没有出现宕机的情况.
代码语言:javascript复制xiaoxu:PRIMARY> rs.status();
{
"set" : "xiaoxu",
"members" : [
{
"_id" : 0,
"name" : "10.130.9.149:37017",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY",
"uptime" : 42307,
"optime" : {
"ts" : Timestamp(1597106283, 1),
"t" : NumberLong(2)
},
},
{
"_id" : 1,
"name" : "10.130.10.149:37017",
"health" : 0,
"state" : 8,
"stateStr" : "(not reachable/healthy)",
"uptime" : 0,
"optime" : {
"ts" : Timestamp(0, 0),
"t" : NumberLong(-1)
},
},
{
"_id" : 2,
"name" : "10.130.10.150:37017",
"health" : 0,
"state" : 8,
"stateStr" : "(not reachable/healthy)",
"uptime" : 0,
"optime" : {
}
],
"ok" : 1
}
xiaoxu:PRIMARY>
5、处理剩下2个节点异常
直接启动原主库与原从节点会自动加入到副本集中且不会重新全量重新初始化(前提是必须在oplog恢复窗口内),相比standalone方式要快很多,尤其副本集成员数据量很大的情况,在线全量初始化很慢且会对新主库造成性能问题.
【10.130.9.149--原主库】
代码语言:javascript复制mongod -f /opt/mongo37017/conf/mongodb37017.conf
child process started successfully, parent exiting
mongo 127.0.0.1:37017
xiaoxu:SECONDARY>
xiaoxu:SECONDARY>
xiaoxu:SECONDARY> rs.status();
{
"set" : "xiaoxu",
"date" : ISODate("2020-08-11T13:09:00.890Z"),
"myState" : 2,
"term" : NumberLong(2),
"syncingTo" : "10.130.9.149:37017",
"syncSourceHost" : "10.130.9.149:37017",
"members" : [
{
"_id" : 0,
"name" : "10.130.9.149:37017",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY",
},
{
"_id" : 1,
"name" : "10.130.10.149:37017",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 44954,
"optime" : {
"ts" : Timestamp(1597151334, 1),
"t" : NumberLong(2)
},
"optimeDate" : ISODate("2020-08-11T13:08:54Z"),
"syncingTo" : "10.130.9.149:37017",
"syncSourceHost" : "10.130.9.149:37017",
"syncSourceId" : 0,
"infoMessage" : "",
"configVersion" : 37248,
"self" : true,
"lastHeartbeatMessage" : ""
}
6、重新修改节点优先级别与投票权【别忘记,否则副本集变成单节点】
代码语言:javascript复制xiaoxu:PRIMARY> config=rs.config();
{
"_id" : "xiaoxu",
"members" : [
{
"_id" : 0,
"host" : "10.130.9.149:37017",
"arbiterOnly" : false,
"buildIndexes" : true,
"hidden" : false,
"priority" : 1,
"tags" : {
},
"slaveDelay" : NumberLong(0),
"votes" : 1
},
{
"_id" : 1,
"host" : "10.130.10.149:37017",
"arbiterOnly" : false,
"buildIndexes" : true,
"hidden" : false,
"priority" : 0,
"tags" : {
},
"slaveDelay" : NumberLong(0),
"votes" : 0
},
{
"_id" : 2,
"host" : "10.130.10.150:37017",
"arbiterOnly" : false,
"buildIndexes" : true,
"hidden" : false,
"priority" : 0,
"tags" : {
},
"slaveDelay" : NumberLong(0),
"votes" : 0
}
xiaoxu:PRIMARY> config.members[1].priority=1
0
xiaoxu:PRIMARY> config.members[1].votes=1
0
xiaoxu:PRIMARY> config.members[2].votes=1
0
xiaoxu:PRIMARY> config.members[2].priority=1
【此时不需要加force,通常情况不建议force】
xiaoxu:PRIMARY> rs.reconfig(config);
{ "ok" : 1 }
xiaoxu:PRIMARY>
【总结】
1、通过standalone方式强制提升从节点为主,如异常节点此时恢复也无法直接加入副本集,需要重新全量初始化【此方式不推荐】
2、方式2在不改变副本集成员数的情况下,只是修改成员属性来快速提升从为主,这种方式应该最优雅也是推荐方式的(感谢mongo群里面星哥的讲解.)【此方式推荐】
欢迎大家提宝贵的建议,我是小徐,非常感谢.