在我们的产品中,我们有一个核心集合,可以从一组分布式工作人员访问。
我希望能够从集合中获取文档,而不会让任何工作人员意外地拿起相同的文档。
到目前为止我为防止重复记录加载而提出的最佳方法如下:
拥有2个具有以下基本结构的独立集合:
core: { _id: '{mongoGeneratedId}', locked: false, lockTimeout: 0}
lock: { _id: null, lockTimeout: 0}
(lockTimeout将有一个TTL索引)
工作人员将运行如下所示的查询:
db.core.findOne({
$or: [
{locked: false},
{lockTimeout < $currentTime}
]
})
并会返回一条记录。
要测试记录是否已被其他工作人员抓取并锁定,则会尝试将记录插入锁定中,锁定时间为5分钟,其核心ID与核心表中的ID相同。
如果失败,那么我们知道另一名工作人员将我们推到了帖子中,我们想再次尝试运行查询。如果成功,那么我们更新core以锁定为true并使lockTimeout与lock集合中的lockTimeout相同。
除了增加某种形式稍微复杂的排序以减少2名工人获得相同记录的机会之外我相信这应该有效。
然而,它并不优雅,我觉得应该有一个更好的方法,不要求我创建一个二级集合,只是为了跟踪锁定。
这样的事情存在吗?亲切的问候!
答案 0 :(得分:3)
尝试使用findAndModify
命令。此命令以原子方式更新文档并返回文档(默认预置,可选择更新后)。您可以使用原子更新来锁定文档:
> db.queue.insert({ "x" : 1, "locked" : false })
> db.queue.findAndModify({
"query" : { "locked" : false },
"update" : { "$set" : { "locked" : true } }
})
{ "_id" : ObjectId("53ea6f0ef9b63e0dd3ca1a1f"), "x" : 1, "locked" : false }
您也可以原子地删除文档。查看链接,了解可能有助于类似队列的用例的所有功能,并阅读有关命令行为的更多信息。