首页 > 解决方案 > 在 MongoDB 副本集中读取自己的写入。随意的一致性不起作用?

问题描述

我在一个 3 成员副本集中使用 mongodb,试图读取我自己的写入。然而,我似乎从我的阅读中得到了陈旧的数据。根据文档,通过“多数”问题进行读/写,它应该保证:

“读操作反映了它们之前的写操作的结果。”

2018年的这篇文章中也有同样的说法:

具有读取关注多数的因果读取 R1 等待看到 T1 多数已提交,然后返回成功。

然而,我似乎没有这么幸运。下面的代码插入一个用户,并立即尝试通过 ID 找到同一用户。这是在一个循环中完成的,只需要 1-3 次迭代,它就会因“找不到用户”而失败。

IMongoCollection<User> collection = MongoDatabase.GetCollection<User>("UserCollection")
    .WithReadConcern(ReadConcern.Majority)
    .WithWriteConcern(WriteConcern.WMajority)
    .WithReadPreference(ReadPreference.Secondary);

Random rnd = new Random();

while (true)
{
    User newUser = new User
    {
        Email = $"{rnd.Next(int.MinValue, int.MaxValue)}@gg.com"
    };

    collection.InsertOne(newUser);

    if (newUser.Id == ObjectId.Empty)
    {
        throw new Exception("Id is empty");
    }

    var findFluent = collection.Find(Builders<User>.Filter.Eq(x => x.Id, newUser.Id));
    User foundUser = findFluent.FirstOrDefault();

    if (foundUser == null)
    {
        throw new Exception("User not found");
    }
}

我已经为读/写指定了“多数”问题。为了测试,我将“次要”指定为阅读偏好。如果我将“Primary”指定为读取首选项,这将永远不会失败(显然)。

我究竟做错了什么?

标签: mongodbmongodb-queryreplicaset

解决方案


首先,您的链接中描述的因果一致性需要在会话中执行操作。我没有在您的代码中看到会话使用。

其次,大多数阅读关注意味着:

读取关注“多数”保证读取的数据已被大多数副本集成员确认(即读取的文档是持久的并且保证不会回滚)。

这并不能保证返回的数据是文档的最新版本。如果您正在执行辅助读取,您将获得截至该辅助节点的集群时间提交给大多数节点的数据,这可能落后于主节点的集群时间。

根据this note,您需要一个会话来获得与大多数阅读关注点的因果一致性。


推荐阅读