0
点赞
收藏
分享

微信扫一扫

mongodb中PSA架构的Secondary宕机会怎样

关于副本集中的votes

今天有和同事聊到一个问题,这个问题就是PSA中的仲裁节点也是具有Votes属性的,那么在Secondary宕机的时候是不是仲裁节点也能确认majority写关注。

先来看看文档中的说明


​​Hidden​​​, ​​delayed​​​, and ​​priority 0​​​ members with ​​members[n].votes​​​ greater than ​​0​​​ can acknowledge ​​"majority"​​ write operations.

Delayed secondaries can return write acknowledgment no earlier than the configured ​​secondaryDelaySecs​​.

在文档中提到的是,对于掩藏节点和延迟节点来说,配置votes大于0可以用来确认Majority写关注,其中对于掩藏节点来说,确认的时间不早于secondaryDelaySecs参数的配置。在这一段描述中,并没有提到仲裁节点也能确认Majority,很显然,因为仲裁节点中是没有数据的,所以的仲裁节点没办法去确认Majority写操作。

研究PSA中的Secondary宕机会有什么影响

在文档中有一篇​​文章​​专门介绍了如何减轻PSA架构的中Secondary宕机导致的性能影响。主要的影响在如下几个方面:

Majority的写入无法完成

在PSA结构的副本集中,我们可以看到"writeMajorityCount" : 2,也就是说要完成一个Majority写入,需要得到两个节点的确认。在PSA的架构中,仲裁节点是不会存储数据的,同时就算Secondary宕机,也不会导致writeMajorityCount的变化,它的数值始终为2.这样就导致了majority写入无法完成。在5.0的版本中,默认的写关注已经被设置为Majority,所以会带来明显的影响。

测试

当Secondary宕机的时候,发现一个普通的写入已经无法完成

mongodb中PSA架构的Secondary宕机会怎样_mongodb

需要注意的是,虽然说看上去这个insert是被阻塞的,但是实际上已经完成了对primary的插入,只是无法收到Secondary的确认,所以使用local读关注的时候是可以查看到数据的,就算kill掉那个insert,这个insert也不会回滚。

rs0:PRIMARY> db.test.find().readConcern("majority")
{ "_id" : ObjectId("62bd14553caefa98d3edf075"), "a" : "w1t5" }
{ "_id" : ObjectId("62c3f2e92bce0e4b14004db1"), "a" : 1 }
{ "_id" : ObjectId("62c3f305fb1fc227b09aba9b"), "a" : 1 }
rs0:PRIMARY> db.test.find().readConcern("local")
{ "_id" : ObjectId("62bd14553caefa98d3edf075"), "a" : "w1t5" }
{ "_id" : ObjectId("62c3f2e92bce0e4b14004db1"), "a" : 1 }
{ "_id" : ObjectId("62c3f305fb1fc227b09aba9b"), "a" : 1 }
{ "_id" : ObjectId("62c3f41d2bce0e4b14004db2"), "a" : 2 }
{ "_id" : ObjectId("62c3f50bfb1fc227b09aba9c"), "a" : "S_DOWN" }

此时,系统已经出现故障了,如果不做任何处理,那么就是所有的写入会被hang住。既然已经知道hang住的原因是因为默认写关注的问题,那么就可以尝试使用修改默认写关注的方式临时”解决”(打引号的解决)。

--修改默认写关注,在敲入这个命令之后你会发现依然是被hang住的,但是在别的终端可以查看已经修改完成,结束
db.adminCommand({
"setDefaultRWConcern" : 1,
"defaultWriteConcern" : {
"w" : 1
}
})
--使用db.serverstatus()确认
"defaultRWConcern" : {
"defaultReadConcern" : {
"level" : "local"
},
"defaultWriteConcern" : {
"w" : 1,
"wtimeout" : 0
},

--此时在做insert发现可以完成
rs0:PRIMARY> db.test.insert({a:"S_DOWN_W1"})
WriteResult({ "nInserted" : 1 })

那么到目前为止,问题解决了吗?没有,因为就算可以写入了,依然会带来下面的问题

造成主库内存压力的增加

在Secondary宕机的情况下,主库的写入没办法被大多数节点确认,所以造成了Majority Commit Point没办法推进。在这里可能会有一些疑问,就是大不了我将默认读关注修改为非Majority不就没关系了吗。需要了解到的是,修改了默认读关注这只是对于客户端的行为,wiredTiger依然会在内存中维护Majority Commit Point的信息,以及生成快照。并且在Majority Commit Point无法推进的时候,这些数据也是无法做checkpoint的。脏数据无法做checkpoint,当脏数据很多的时候就会造成内存使用不断的增加。

到目前为止已经知道内存压力大的原因,那么就可以知道如果要解决这个问题,可以尝试关闭majorityReadConcern,这样就可以让WT不维护Majority Commit Point的信息,减少内存的压力。

测试

使用fake2db工具往副本集中写入大量的数据

[root@vm002 fake2db]# ./fake2db --rows 2000000 --db mongodb --name mydb --host 192.168.202.203 --port 27017  --custom phone_number./fake2db --rows 2000000 --db mongodb --name mydb --host 192.168.202.203 --port 27017  --custom phone_number

Oplog的大量增长

在Secondary宕机的情况下,Mongodb会允许OPLOG的大小超过配置的大小,也就是说如果不加以处理会导致OPLOG占用大量的磁盘空间。


重启主库需要花费更多的时间

重启之前查看mongodb状态

rs0:PRIMARY> rs.status().lastStableRecoveryTimestamp
Timestamp(1657009141, 1)
rs0:PRIMARY> var timestamp = Timestamp(1657009141, 958);
rs0:PRIMARY> print( new Date( timestamp.t*1000+timestamp.i))
Tue Jul 05 2022 16:19:01 GMT+0800 (CST)

重启

mongod --shutdown本质上是后台的kill操作

mongod --shutdown -f /etc/mongod_1.conf
mongod -f /etc/mongod_1.conf

重启之后检查状态

rs0:PRIMARY> rs.status().lastStableRecoveryTimestamp
Timestamp(1657009141, 1)
rs0:PRIMARY> var timestamp = Timestamp(1657009141, 958);
rs0:PRIMARY> print( new Date( timestamp.t*1000+timestamp.i))
Tue Jul 05 2022 16:19:01 GMT+0800 (CST)

在重启之后会发现,lastStableRecoverTimestamp还是之前的时间点,意味着如果主库再次发生异常重启,那么还是会发生从lastStableRecoverTimestamp开始的实例恢复。


可能会发生数据的丢失

当前主节点的成员在故障转移后重新加入其副本集时,回滚将恢复其上的写操作。假设在Secondary宕机之后我们停止了主库,在重启的过程中我们先启动了备库,因为之前对主库的那些写操作是没有同步到备库的,那么原来的主库作为Secondary加入副本集之后就会发生回滚的操作。

rs0:ROLLBACK> rs.status().members
[
{
"_id" : 0,
"name" : "vm002:27017",
"health" : 1,
"state" : 9,
"stateStr" : "ROLLBACK", <----节点处于rollback状态
"uptime" : 218,
"optime" : {
"ts" : Timestamp(1657027286, 1),
"t" : NumberLong(14)
},
"optimeDate" : ISODate("2022-07-05T13:21:26Z"),
"lastAppliedWallTime" : ISODate("2022-07-05T13:21:26.199Z"),
"lastDurableWallTime" : ISODate("2022-07-05T13:21:26.199Z"),
"syncSourceHost" : "vm002:27018",
"syncSourceId" : 3,
"infoMessage" : "",
"configVersion" : 48389,
"configTerm" : 15,
"self" : true,
"lastHeartbeatMessage" : ""
},

在主机层面也可以发现存在rollback文件

[root@vm002 rollback]# ls
8e2761dd-ac59-4119-b1d3-6d299273e2ab c3282743-5de8-49d3-9310-99c77f91a04c
b08528ee-783e-437a-bbf7-6bb4b0b51514 f3fda89b-89b9-43f3-ac3e-792df28e6e3e


官方提供的解决方式

​​在这篇文章中​​提到了如何解决PSA架构S宕机的问题,那就是将问题节点(也就是宕机的Secondary)的votes和priority都修改为0,当修改了votes参数之后,就可以让writeMajorityCount的值由之前的2变成1,那么这样就能解决内存压力的问题,因为当writeMajorityCount为1的时候,一个节点就能完成majority写入。在secondary恢复之后在使用rs.reconfigForPSASet() 将其notes和priority修改为1即可。

cfg = rs.conf();
cfg.members[0].priority=0
cfg.members[0].votes=0
rs.reconfig(cfg);

rs0:PRIMARY> rs.status()
{
"set" : "rs0",
"date" : ISODate("2022-07-05T13:57:17.357Z"),
"myState" : 1,
"term" : NumberLong(15),
"syncSourceHost" : "",
"syncSourceId" : -1,
"heartbeatIntervalMillis" : NumberLong(2000),
"majorityVoteCount" : 2,
"writeMajorityCount" : 1, <---已经变成1
"votingMembersCount" : 2,

这个时候,写入都可以成功,但是仍然需要关心OPLOG大小的问题。

在Secondary恢复时候,重新加入复制集即可

mongod -f /etc/mongod_1.conf
加入集群之后就能新加入的db1能正常成为复制集的一部分,但是它的votes和priority都是0

rs0:PRIMARY> rs.reconfigForPSASet(0, cfg);
Running first reconfig to give member at index 0 { votes: 1, priority: 0 }


Running second reconfig to give member at index 0 { priority: 1 }
{
"ok" : 1,
"$clusterTime" : {
"clusterTime" : Timestamp(1657030687, 1),
"signature" : {
"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId" : NumberLong(0)
}
},
"operationTime" : Timestamp(1657030687, 1)
}

引用

更加全面的文章在这里

​​https://zhuanlan.zhihu.com/p/531480042​​


举报

相关推荐

0 条评论