【发布时间】:2011-12-26 06:25:16
【问题描述】:
我正在将我的应用程序从 App Engine 数据存储区移植到 MongoDB 后端,并且对“文档更新”的一致性有疑问。我知道一个文档上的更新都是原子的和孤立的,但是有没有办法保证它们在不同的副本集之间是“一致的”?
在我们的应用程序中,许多用户可以(并且将会)尝试通过在一次更新期间向其中插入一些嵌入式文档(对象)来同时更新一个文档。我们需要确保这些更新在所有副本中以逻辑一致的方式发生,即当一个用户将一些嵌入文档“放入”父文档中时,其他用户不能将他们的嵌入文档放入父文档中,直到我们确保他们已经阅读并收到第一个用户的更新。
所以我所说的一致性是指我们需要一种方法来确保如果两个用户尝试恰好同时对一个文档执行更新,MongoDB 只允许其中一个更新通过,并丢弃另一个(或至少防止两者发生)。我们不能在这里使用标准的“分片”解决方案,因为单个更新不仅仅包含增量或减量。
保证一个特定文档的一致性的最佳方法是什么?
【问题讨论】:
-
我认为您将功劳归于错误的答案。这里的诀窍是原子操作 +
findAndModify。在您的情况下,您希望findAndModify带有时间戳,以便后续写入失败,直到读取器刷新。 -
@GatesVP 这两个答案都很好,我鼓励大家阅读这两个答案,以形成更完整的 MongoDB 一致性图景。我选择了 mnemosyn 的回复,因为它解释了 MongoDB 的“写关注”策略以及安全与不安全读取的核心概念。我已经看过像 dcrosta 这样的例子,但需要准确地知道“不安全”读取可以保证和不能保证的内容。
-
在真实的分布式数据库世界中,你不能依赖时间戳来确定顺序。不同的节点可能(并且将会)有不一致的时钟。如果我们可以使用时间戳,我们就不需要像 Paxos 这样的共识协议。但是由于 MongoDB 本质上是一个单主数据库,因此可以随意使用时间戳。只是不要问哪种方式比旧的 *SQL 更好。
标签: mongodb concurrency optimistic-locking consistency