使用w = 0的Mongodb更新保证

时间:2014-11-14 16:04:25

标签: mongodb pymongo mongodb-query

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

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

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

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

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

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

2 个答案:

答案 0 :(得分:2)

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

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

  

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

这意味着写入可能在MongoDB本身内无声地失败。

如果您希望特别保证,这是不可靠的。在一天结束时,如果您想触摸数据库并从中获得确认,那么您必须等待,物理定律。

答案 1 :(得分: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完全超载(例如150k在带有旋转磁盘的独立mongod上更新一秒),当然可能会出现问题,尽管通常从底层操作系统的持久性角度来看也是如此。

但是,如果写入问题为w:0,j:0,并且在更新未同步到日志时发生中断,则更新仍可能会在发生中断时无声地消失。

注意:

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