添加新成员期间二级数据的陈旧数据与多数关注

问题描述

给定一个由 1 个主要 + 1 个次要 + 1 个仲裁者组成的基本副本集,启用了 mongo 4.0 和多数,我们遇到了一个无法解释的奇怪问题

我们想向副本集添加一个新的辅助节点。所以我们启动了一个新的VM,安装并配置了mongod,然后将节点添加replicaset。新成员以 STARTED2 状态出现并且正在与现有集群同步。到目前为止一切顺利。

但是我们注意到了一些事情:我们的一个从辅助数据读取的应用程序(readPref:secondaryPreferred,readConcern:massive)正在读取陈旧数据(从同步开始的日期开始)。看看 rs.status(),确实 lastCommittedOpTime 卡在了过去。 正如预期的那样,主节点的有线虎缓存使用率开始增加,达到 15% 到 20% 的区域,并开始减慢主节点的速度。

我们最终通过在同步时将成员声明为隐藏来解决问题,但是:为什么会发生这种情况?

我的理解是,在大多数成员确认所述数据之前,数据不会提交到“主要”区域。但是对于 3 个数据成员(主要 + 次要 + 新次要),大多数应该已经与现有成员会面了。为什么添加新成员会导致这种行为?

解决方法

“多数”是指投票节点的多数。

在原始集群中,Primary、Secondary 和 Arbiter 各有 1 票,因此多数票为 2。写入一旦写入主服务器和辅助服务器,就被视为多数提交。

添加新节点后,有 4 票,Primary、原始 Secondary、新 Secondary、Arbiter。

这意味着 2 不再是多数,它只是一半。因此,为了被视为多数提交,它必须写入 3 个投票节点,即主节点和两个辅助节点。

每个复制的节点都以相同的顺序保存操作日志,并记录已知已提交给大多数节点的最新操作。这称为多数提交点。任何请求多数读取关注的读取都将使用截至多数提交点的数据快照。

一旦添加了新节点,在完成初始同步并开始应用 oplog 之前,多数写入将无法完成。在那之前,所有多数读取都将是最近的多数提交点,就在添加该节点之前。

简单修复:移除仲裁器。 这将使集群返回到 3 个投票节点,并且多数写入将能够在仅主节点和一个辅助节点确认写入的情况下完成。