4

我的 MongoDB 集合用作作业队列,并且有 3 台 C++ 机器从该集合中读取。问题是这三个人不能完成同样的工作。所有工作只需要完成一次。

我通过使用“isDone:False”在集合中搜索所有记录来获取所有未完成的作业,然后更新此文档“isDone:True”。但是如果两台机器同时找到同一个文件,它们就会同时做同一个工作。我怎样才能避免这种情况?

编辑:我的问题是 - findAndModify 真的解决了这个问题吗?(看完MongoDb的findAndModify中确保独占读取的一种方式?

4

2 回答 2

1

是的,查找并修改将解决您的问题:

db.collection.findAndModify( { query: { isDone: false }, update: { $set: { isDone: true } }, new: true, upsert: false # 从不创建新文档 } );

这将返回一个刚刚从 false 更新为 true 的文档。

但是,如果您的 C++ 客户端出现故障(盒子死机、它们被杀死、代码有错误等),您就会遇到一个严重的问题。想象一下,如果您的 TCP 连接在服务器更新之后但在 C++ 之前断开代码得到了这份工作。通常最好采用多阶段方法:

  • 将“isDone”更改为“isInProgress”,完成后,删除文档。(现在,你可以看到“待办事项”和“正在完成”的堆栈。如果某件事“正在完成”很长时间,客户端可能已经死了。

  • 将“isDone”更改为“phase”并将其从“new”自动设置为“started”(稍后将其设置为“finished”)。现在你可以看到如果某件事“启动”了很长时间,客户端可能已经死了。

如果你真的很老练,你可以做一个部分索引。例如,“仅索引具有“phase:{ $ne: 'finished'}”的文档。现在您无需浪费空间来索引数百万个已完成的文档。索引仅包含少数新的/正在进行的文档,所以它更小/更快。

于 2013-04-24T02:40:26.660 回答
1

是的,findAndModify 解决了。

参考:MongoDB findAndModify from multiple clients "... 注意:此命令在受影响的数据库上获得写锁,并将阻塞其他操作,直到它完成;然而,通常写锁是短暂的,相当于其他类似的 update()操作……”

参考:http : //docs.mongodb.org/manual/reference/method/db.collection.update/#db.collection.update “...对于非分片集合,您可以使用 $isolated 隔离运算符覆盖此行为,它将更新操作隔离并在更新期间阻止其他写入操作。请参阅隔离运算符。..."

参考:http ://docs.mongodb.org/manual/reference/operator/isolated/

问候, 莫西

于 2013-04-24T02:09:54.243 回答