接上一篇MongoDB PSA架构痛点以及如何应对有朋友指出,5.0分片集群采用PSA时,出现S宕机时,客户端写入hang,并没有按官方文档描述那样PSA默认写是w:1.我当初只是验证PSA副本集发现与官方描述一致,但并没有验证分片架构.导致存在偏差.
【分析与验证过程】
【验证PSA副本集模式】
1、PSA副本集默认写关注
shard2:PRIMARY> db.adminCommand({getDefaultRWConcern:1})
{
"defaultReadConcern" : {
"level" : "local"
},
"defaultWriteConcernSource" : "implicit",
"defaultReadConcernSource" : "implicit",
"localUpdateWallClockTime" : ISODate("2022-05-17T06:03:42.239Z"),
},
2、验证50 PSA版本默认writeConcern
备注:关闭一个数据节点后写入是否正常.
shard2:PRIMARY> cfg.members[0].stateStr
PRIMARY
shard2:PRIMARY> cfg.members[1].stateStr
(not reachable/healthy)
shard2:PRIMARY> cfg.members[2].stateStr
ARBITER
shard2:PRIMARY> use test
switched to db test
--没有指定writeConcern成功写入
shard2:PRIMARY> db.testDefaultWriteConcern.insert({w:1})
WriteResult({ "nInserted" : 1 })
--指定写入失败,说明默认majority而是官方说w:1
shard2:PRIMARY>db.testDefaultWriteConcern.insert({w:1},{writeConcern:{w:"majority",wtimeout:1000}})
WriteResult({
"nInserted" : 1,
"writeConcernError" : {
"code" : 64,
"codeName" : "WriteConcernFailed",
"errmsg" : "waiting for replication timed out",
"errInfo" : {
"wtimeout" : true,
"writeConcern" : {
"w" : "majority",
"wtimeout" : 1000,
"provenance" : "clientSupplied"
}
}
}
})
【分片使用单个PSA shard来验证来验证默认写关注级别】
1、查看集群信息
mongos> sh.status()
--- Sharding Status ---
shards:
{ "_id" : "shard2",
"host" : "shard2/10.230.10.150:21017,10.230.9.150:21017", "state" : 1,
"topologyTime" : Timestamp(1652772600, 4) }
active mongoses:
"5.0.2" : 1
autosplit:
Currently enabled: yes
databases:
{ "_id" : "config", "primary" : "config", "partitioned" : true }
2、创建分片集合
mongos> sh.enableSharding("xiaoxu")
{
"ok" : 1,
}
mongos> sh.shardCollection("xiaoxu.testDefaultWriteConcern",{_id:"hashed"})
{
"collectionsharded" : "xiaoxu.testDefaultWriteConcern",
"ok" : 1,
}
3、正常情况插入测试数据
备注:不管采用默认writeConcern还是采用w:1或者w:"majority"模式都没有问题
mongos> use xiaoxu
switched to db xiaoxu
mongos> db.testDefaultWriteConcern.insert({_id:1,name:"xiaoxu"})
WriteResult({ "nInserted" : 1 })
mongos>db.testDefaultWriteConcern.insert({_id:2,name:"xiaoxu"},{writeConcern:{w:"majority",wtimeout:1000}})
WriteResult({ "nInserted" : 1 })
mongos>db.testDefaultWriteConcern.insert({_id:3,name:"xiaoxu"},{writeConcern:{w:1}})
WriteResult({ "nInserted" : 1 })
4、模拟PSA副本中S宕机的场景来插入数据
备注:手动关闭从实例
shard2:PRIMARY> cfg.members[0].stateStr
PRIMARY
shard2:PRIMARY> cfg.members[1].stateStr
(not reachable/healthy)
shard2:PRIMARY> cfg.members[2].stateStr
ARBITER
mongos> db.testDefaultWriteConcern.insert({_id:6,name:"xiaoxu"},{w:1})
WriteResult({ "nInserted" : 1 })
mongos>
mongos>
mongos>db.testDefaultWriteConcern.insert({_id:7,name:"xiaoxu"},{w:"majority",wtimeout:10000})
WriteResult({
"nInserted" : 1,
"writeConcernError" : {
"code" : 64,
"codeName" : "WriteConcernFailed",
"errmsg" : "waiting for replication timed out; Error details: { wtimeout: true, writeConcern: { w: \"majority\", wtimeout: 10000, provenance: \"clientSupplied\" } } at shard2",
"errInfo" : {
}
}
})
异常:此时没有指定writeConcern,采用默认的行为.此时写入hang住.
mongos> db.testDefaultWriteConcern.insert({_id:8,name:"xiaoxu"})
5、分片下写入数据默认的writeConcern来源哪里?
备注:查询发现defaultWriteConcern是w:majority.这个信息是来自于config.而不是shard层面.目前config是单节点的副本集.尝试改成PSA架构试试?
mongos> db.adminCommand({getDefaultRWConcern:1})
{
"defaultReadConcern" : {
"level" : "local"
},
"defaultWriteConcern" : {
"w" : "majority",
"wtimeout" : 0
},
"defaultWriteConcernSource" : "implicit",
"defaultReadConcernSource" : "implicit",
}
6、尝试把config副本集改成PSA架构
备注:confg副本集中禁止加入仲裁节点.那么config默认是writeConcern就是{w:majority}.
config:PRIMARY> rs.reconfigForPSASet(2, cfg);
Running first reconfig to give member at index 2 { votes: 1, priority: 0 }
{
"ok" : 0,
"errmsg" : "Arbiters are not allowed in replica set configurations being used for config servers",
"code" : 103,
"codeName" : "NewReplicaSetConfigurationIncompatible",
"$gleStats" : {
"lastOpTime" : {
"ts" : Timestamp(1652693376, 3),
"t" : NumberLong(1)
}
7、针对分片集群下DefaultRWConcern相关说明
解释;
1、连接到mongos时没有显式指定writeConcern时,mongos使用全局默认设置,这个全局设置来自config副本集,而不是底层分片,所有底层分片PSA下架构默认writeConcern:{w:1}直接被config副本集全局设置覆盖.因为config不支持仲裁,所以默认是writeConcern:{w:"majority"}
8、5.0 PSA出现S宕机时,为了避免上一篇文章提到问题外.还包括如下:
如果客户端没有指定writeConcern采用默认行为会导致写入hang的情况
应对措施:
1、采用方案2.注意是临时的,等从库恢复及时重置回去,否则当主库宕机,没有办法选出新主,从而影响系统可用性,此时从宕机或者机器挂了,需要及时监控并修改配置,否则可能会影响应用使用.
2、修改config默认writeConcern为w:1虽然能解决写入hang问题,但无法解决底层分片内存压力以及性能下降问题等问题.详细查看上一篇文档说明.
9、修改分片中宕机的实例节点信息来验证写入
shard2:PRIMARY> cfg.members[1].priority=0
0
shard2:PRIMARY> cfg.members[1].votes=0
0
shard2:PRIMARY> rs.reconfig(cfg)
10、再次验证mongos插入数据
备注:经过修改后,不管是否指定writeConcern还是指定majority都可以。
注意:应用此时指定w:2就有问题.
mongos> db.testDefaultWriteConcern.insert({_id:9})
WriteResult({ "nInserted" : 1 })
mongos>db.testDefaultWriteConcern.insert({_id:10},{writeConcern:{w:"majority",wtimeout:1000}})
WriteResult({ "nInserted" : 1 })
总结:至此完成分析PSA架构包括集群下使用PSA分片存在问题以及对应方案,不管怎么应对,都需要注意潜在的影响.例如当单个数据节点宕机或者长延迟时,可以通过程序定时检测节点状态,出现异常时临时将优先级别与投票设置0来避免5.0分片集群下默认多节点写入导致hang或者客户端指定多节点写入hang问题.由此带来一致性问题与高可用性问题需要关注的.