暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

MongoDB 案例分享:stepDown() 命令报错解决方法

原创 肯肯在学习 2022-10-18
999

我们可以在 Percona 看到并解决许多不同的问题。这是最近让我挠头一段时间的最新消息。

场景

我们有一个运行 MongoDB 4.0 的分片集群环境,需要升级到 MongoDB 4.2。容易吧?这个环境的唯一特别之处是 MongoDB 在 AWS 的自定义 Docker 环境中运行。

我们从禁用平衡器并首先升级配置服务器的副本集的常用方法开始。在这种情况下,配置服务器的副本集有三个运行 MongoDB 4.0 的成员。我们没有就地升级它们,而是选择添加三个运行 MongoDB 4.2 的新成员。所以现在我们总共有六个节点。下一步是将主节点降级到新的 4.2 节点之一,最后停用旧服务器。

测试迁移计划

我们从非生产环境中的计划开始。起初,一切都很好;我们将配置服务器的副本集设置为六个成员并设置优先级,以便新的 4.2 服务器之一是从当前服务器降级后成为主服务器的唯一候选者。所以我们继续像往常一样运行_rs.stepDown()_命令,这就是事情开始出错的时候。客户突然开始报告以下消息:

2022-07-15T14:49:59.629+0000 W  NETWORK  \[ReplicaSetMonitor-TaskExecutor\] Unable to reach primary for set testrs-cfg

我的第一个想法是网络层一定有问题,但检查所有主机之间的连接没有问题。接下来,我们查看了 Docker,但那里似乎一切正常。

深层原因探究

我们在本地连接到配置为主服务器的服务器,在那里我们看到了一个奇怪的情况。服务器无法完成升级过程成为主服务器,并且已经完成了一半:

testrs-cfg:PRIMARY> db.isMaster() { "hosts" : [ "host1:27019", "host2:27019" ], "passives" : [ "host3:27019", "host4:27019", "host5:27019", "host6:27019" ], "setName" : "testrs-cfg", "setVersion" : 77, "ismaster" : false, "secondary" : true, "primary" : "host6:27019", "me" : "host6:27019", …

查看最后四行,我们可以看到 host6 应该是主要的,但它没有被完全提升。我们还检查了_db.currentOp()_,它显示所有会话似乎都在等待一些与副本集状态转换相关的锁,并且以下操作似乎卡住了为_config.chunks_集合创建索引:

{ "type" : "op", "host" : "host6:27019", "desc" : "rsSync-0", "active" : true, "currentOpTime" : "2022-07-18T12:07:22.381+0000", "effectiveUsers" : [ { "user" : "__system", "db" : "local" } ], "opid" : 2800, "secs_running" : NumberLong(5), "microsecs_running" : NumberLong(5494726), "op" : "command", "ns" : "config.$cmd", "command" : { "createIndexes" : "chunks", "indexes" : [ { "name" : "ns_1_min_1", "key" : { "ns" : 1, "min" : 1 }, "unique" : true } ], "$db" : "config" }, "numYields" : 0, "waitingForLatch" : { "timestamp" : ISODate("2022-07-18T12:07:16.990Z"), "captureName" : "ReplicationCoordinatorImpl::_mutex" }, "locks" : { "ReplicationStateTransition" : "W" }, "waitingForLock" : false,

奇怪的是这个集合只包含几个文档,所以这个操作应该很快(索引也已经存在)。

在这一点上,我们怀疑我们可能遇到了一些错误,并开始查看报告的关于 stepDown/stepUp 过程中死锁的许多问题。不幸的是,我们再次空手而归。

解决方案

接下来,我们检查了配置服务器副本集本身的配置,并在_rs.conf()_的“设置”部分发现了一些不寻常的地方:

"settings" : { "chainingAllowed" : true, "heartbeatIntervalMillis" : 2000, "heartbeatTimeoutSecs" : 10, "electionTimeoutMillis" : 10000, "catchUpTimeoutMillis" : -1, "catchUpTakeoverDelayMillis" : 30000, "getLastErrorModes" : { }, "getLastErrorDefaults" : { "w" : "majority", "j" : true, "wtimeout" : 0 }, "replicaSetId" : ObjectId("62cd9b0d1bb173ee7be7f2ef") } }

在运行_rs.initialize()时,大多数情况下都会省略_getLastErrorDefaults_设置,因为写入问题通常是在每个会话的基础上控制的。在这种情况下,配置服务器副本集已使用{ w: most, j: true }的__getLastErrorDefaults_而不是默认值_{ w: 1 }_进行初始化。

我们尝试将副本集配置重置为默认值,如下所示:

cfg=rs.conf() cfg.settings.getLastErrorDefaults= { "w" : 1, "wtimeout" : 0 } rs.reconfig(cfg)

完成此操作后,_rs.stepDown()_完美运行,我们能够将 4.2 主版本安装到位。

结论

这个案例的寓意是,我们应该在第一次提升 MongoDB 4.2 主节点时检查副本集级别的写入关注的默认值。

以前,非默认写入问题对选举来说不是问题,因此在 MongoDB 4.2 中发生了一些变化,触发了这种行为。这个问题是特定于配置服务器的,常规分片副本集不会发生同样的情况。

有趣的是,从 MongoDB 5.0 开始,我们不能再使用_settings.getLastErrorDefaults_为副本集指定默认写入关注点。

这也证明了具有模拟真实生产环境的测试设置的价值,以便能够在这些问题在生产中影响我们之前对其进行测试和捕捉。

原文标题:Tales From the MongoDB Field: When stepDown() Goes Wrong
原文作者:Ivan Groenewold
原文地址:https://www.percona.com/blog/tales-from-the-mongodb-field-when-stepdown-goes-wrong/

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论