【问题标题】:Mongodb eventual consistency on replica-sets when writing on two documents写入两个文档时,副本集上的 Mongodb 最终一致性
【发布时间】:2016-05-30 11:38:00
【问题描述】:

我们有一个客户端连续写入两个文档(使用{w:1})。 例如,原始文件可能是:

{_id: "a", value: 0}, {_id: "b", value: 0}

客户端将文档“a”更新为{_id: "a", value: 1},然后在更新完成后,客户端将文档“b”更新为{_id: "b", value: 1}

之后第二个客户致电find({})。第二个客户端从辅助客户端读取,可能尚未收到所有更改。 显然它可以读取以下状态:

  • {_id:"a",value:0},{_id:"b",value:0}
  • {_id:"a",value:1},{_id:"b",value:0}
  • {_id:"a",value:1},{_id:"b",value:1}

这是主节点上的“真实”状态(在过去的某个时刻)。

第二个客户端能否看到如下状态:{_id:"a",value:0},{_id:"b",value:1}?请注意,该状态在主节点上从未存在过。

附: here的解释说:

Secondary ... 按照它们在 oplog 中出现的顺序应用写操作。

这是否意味着辅助节点会按照它们在主节点上更新的顺序更改其文档?

附: find cursors 是否“冻结”他们正在阅读的文档的状态(即忽略创建光标后所做的更改)?如果我使用find(...).sort({_id:-1}) 或者文档“a”的 id 是“c”(即大于“b”),情况会有所不同吗?

谢谢

【问题讨论】:

    标签: mongodb eventual-consistency mongodb-replica-set


    【解决方案1】:

    第一个问题:是的,辅助节点上的操作与主节点上的操作顺序相同。所有操作都记录在oplog。 oplog 本身不是所执行查询的日志(即 updateMany()),而是必须对实际文档执行的操作,以便它的操作成为幂等的。

    关于光标操作。在遍历光标时可能会发生文档移动或更新的情况。如果在更新过程中索引或存储位置发生变化,甚至可能会出现同一文档在光标上出现两次的情况。

    有一种特殊的snapshot 模式可以提供某种隔离,但它有一些限制,即它不能与分片一起使用

    【讨论】:

    • 也感谢光标的解释。
    【解决方案2】:

    如果我们的文档网络是按主服务器上的序列更新的

    1. 换A
    2. 改变B
    3. 改变C

    然后辅助节点会以相同的顺序更新文档:

    1. 更改 A

      可以在不应用其他更改的情况下读取文档

    2. 更改 B

      可以在不应用其他更改的情况下读取文档

    3. 改变C

    对于锁定see this,因为 mongo 可以优化操作顺序,即使触发文档更新继续进行也可以允许读取。

    【讨论】:

    • find 操作呢?如果find按顺序找到两个文档“a”和“b”,是否可以返回更改前的文档“a”和更改后的文档“b”?
    • @Oren - 这是与W:1 相关的所有时间,所以如果find 在辅助处理change B 之前依次失败,那么change A 将被发送回客户端。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-07
    相关资源
    最近更新 更多