我的用例如下 - 我在mongoDB中有一组文档,我必须发送它们进行分析。 文件格式如下 -
{_id:ObjectId(“517e769164702dacea7c40d8”), 日期: “1359911127494”, 状态:“可用”, other_fields ...}
我有一个阅读器流程,它选择状态的前100个文档:可用按 date 排序,并使用 status:processing 修改它们。 ReaderProcess发送文档进行分析。分析完成后,状态将更改为已处理。
目前读者流程首先获取按 date 排序的100个文档,然后将循环中每个文档的状态更新为处理。对于这种情况,有没有更好/更有效的解决方案?
此外,在未来的可扩展性方面,我们可能会使用多个读者进程。 在这种情况下,我希望一个阅读器进程选择的100个文档不会被另一个阅读器进程选中。但是现在提取和更新是单独的查询,因此很多读者进程很可能选择相同的文档。
批量 findAndModify (有限制)可以解决所有这些问题。但不幸的是,它尚未在MongoDB中提供。有没有解决这个问题的方法?
答案 0 :(得分:13)
如你所说,目前没有干净的方法来做你想要的。对于像你需要的那样的操作,目前最好的方法是:
e.g. update({_id:{$in:[<result set ids>]}, state:"available", $isolated:1}, {$set:{readerId:<your reader's ID>, state:"processing"}}, false, true)
)请注意,这甚至可以在高度并发的情况下工作,因为读者永远不会保留其他读者尚未保留的文档(请注意,第2步只能保留当前可用的文档,并且写入是原子的)。如果您希望能够超时预订(例如读者可能崩溃/失败的情况),我会添加一个预约时间的时间戳。
编辑:更多详情:
如果写入时间相对较长,则所有写入操作偶尔会产生挂起操作。这意味着步骤2)可能看不到步骤1)标记的所有文档,除非您采取以下步骤:
另见有关原子性/隔离的讨论的评论。我错误地假设多次更新被隔离。它们不是,或者至少不是默认的。