【问题标题】:Mongodb update guarantee using w=0使用 w=0 的 Mongodb 更新保证
【发布时间】:2015-01-12 02:03:00
【问题描述】:

我有一个包含超过 50 万个文档的大型集合,我需要不断更新这些文档。为了实现这一点,我的第一个方法是使用w=1 来确保写入结果,这会导致很多延迟。

collection.update(
    {'_id': _id},
    {'$set': data},
    w=1
)

所以我决定在我的更新方法中使用w=0,现在性能明显提高了。

由于我过去对 mongodb 的痛苦经历,我不确定在w=0 时是否保证所有更新。我的问题是,是否保证使用w=0 进行更新?

编辑:另外,我想知道它是如何工作的?它是否会创建一个内部队列并一一异步执行更新?我看到使用mongostat,即使在 python 脚本退出后,也正在处理一些更新。还是即时更新?

编辑 2:根据 Sammaye 的回答 link,任何错误都可能导致静默失败。但是,如果提供大量更新会发生什么?那么有些更新会失败吗?

【问题讨论】:

  • 如果这是多线程数据摄取,您不应该看到一点差异。请注意,当您看到 mongostat 中不再发生插入时,插入就完成了,而不是当您的客户端返回时。

标签: mongodb pymongo mongodb-query


【解决方案1】:

不,w=0 可能会失败,只是:

http://docs.mongodb.org/manual/core/write-concern/#unacknowledged

Unacknowledged 类似于忽略的错误;但是,驱动程序将尽可能尝试接收和处理网络错误。

这意味着写入可以在 MongoDB 本身内静默失败。

如果您想具体保证,它是不可靠的。归根结底,如果您希望访问数据库并从中获得确认,那么您必须等待,物理定律。

【讨论】:

  • @Sammae 没有错误,如果给重负载会失败吗?
  • @Dewsworld 因为它应该能够捕获和处理网络错误,如果您在 MongoDB 中没有错误,包括索引错误等,那么机会很小,非常小,可能太小了
  • @Dewsworld 至于内部工作:它将在工作队列中工作,直到完成
【解决方案2】:

w:0 保证更新吗?

正如 Sammaye 所写:不,因为可能有一段时间数据仅应用于内存数据而尚未写入日志。因此,如果在此期间发生中断,具体取决于配置,默认情况下介于 10(j:1 和日志和数据文件位于单独的块设备上)和 100 毫秒之间,您的更新可能会丢失。

请记住,非法更新(例如更改文档的_id)会静默失败。

更新如何与w:0 配合使用?

假设没有网络错误,驱动程序将在将操作发送到带有w:0 的 mongod/mongos 实例后立即返回。但是,让我们进一步了解一下,让您了解幕后发生的事情。

接下来,更新将由查询优化器处理并应用于内存数据集。在成功应用操作后,写入关注w:1 的写入现在将返回。应用的操作将在每个commitIntervalMs 同步到日志,写入关注j:1 除以 3。如果您有{j:1} 的写关注,则驱动程序将在操作存储在日志中成功 后返回。请注意,仍然存在一些边缘情况,其中进入日志的数据不会应用于副本集成员,以防现在发生非常“好”的时间中断。

默认情况下,每隔syncPeriodSecs,日志中的数据就会应用到实际的数据文件中。

关于你在 mongostat 中看到的:它的粒度不是很高,你可能是过去发生的操作。如前所述,内存数据的更新不是即时的,因为更新首先必须通过查询优化器。

重负载是否会导致更新以w:0 静默失败?

一般来说,说“不”是安全的。原因如下:

对于每个连接,都会分配一定数量的 RAM。如果负载太高以至于 mongo 无法分配任何更多 RAM,则会出现连接错误 - 无论写入问题如何,都会处理该错误,但未确认的写入除外。

此外,对内存数据的更新应用非常快 - 很可能仍然比它们来的快以防我们谈论负载峰值。如果 mongod 完全过载(例如,在具有旋转磁盘的独立 mongod 上每秒更新 150k 次),当然可能会出现问题,尽管从持久性的角度来看,底层操作系统通常会利用这一点。

但是,当写入问题为 w:0,j:0 并且中断发生在更新未同步到日志时,更新仍可能会在中断的情况下静默消失。

注意事项:

  1. 最大性能和最小保证持久性之间的最佳平衡是j:1 的写入问题。通过适当的设置,您可以将延迟降低到略高于 10 毫秒。
  2. 若要进一步减少延迟/更新,可能值得查看bulk write operations,如果这些适用于您的用例。根据我的经验,他们经常这样做。在驳回这个想法之前,请阅读并尝试。
  3. 强烈建议不要使用w:0,j:0 进行写入操作,以防您希望对数据持久性有任何保证。使用风险自负。这种写入问题仅适用于“廉价”数据,这些数据很容易重新获取,或者速度问题超出了对持久性的需求。大规模收集实时天气数据就是一个例子——即使这里和那里缺少一两个数据点,系统仍然可以工作。对于大多数应用程序,耐用性一个问题。结论:使用w:1,j:1至少进行持久写入。

【讨论】:

  • "使用 w:1,同步间隔大大减少。" 你有这方面的参考吗?
  • @Sammaye:我认为它在 M102 中被提及。一个简单的测试证明了这一点:在默认设置和 w:1 下,每次写入应该需要大约 30 秒的中位数。
  • 这似乎很奇怪,因为它会使 fsync 队列无用,我已经完成了该课程,但我不记得提到过
  • 另一方面,这可能是我的一个误解——有时不以母语为母语会很痛苦。文档中使用的术语“应用”也很可能是指将数据应用于内存视图。从 mongod 显示的行为来看,这会更有意义。
  • 我自己的理解是w:1表示已经在内存中做了,然后sync设置保持不变就同步了,唯一改变磁盘时间的就是j:1跨度>
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-10
  • 1970-01-01
  • 2013-06-05
  • 1970-01-01
  • 2019-09-04
  • 1970-01-01
相关资源
最近更新 更多