来自多个客户端的MongoDB findAndModify

时间:2013-04-13 13:18:43

标签: mongodb

我的MongoDB集合用作作业队列,有3个C ++计算机可以从这个集合中读取。问题是那三个人不能完成同样的工作。所有工作只需要进行一次。

我通过使用'isDone:False'搜索集合中的所有记录来获取所有未完成的作业,然后更新此文档'isDone:True'。但是,如果2台机器同时找到相同的文档,那么它们都会完成相同的工作。我怎么能避免这个?

编辑:我的问题是 - findAndModify真的能解决这个问题吗? (阅读A way to ensure exclusive reads in MongoDb's findAndModify?

之后

2 个答案:

答案 0 :(得分:1)

是的,findAndModify解决它。

参考:MongoDB findAndModify from multiple clients ” ... 注意:此命令在受影响的数据库上获取写锁定,并在完成之前阻止其他操作;但是,通常写锁是短暂的并且等同于其他类似的update()操作。 ......“

参考:http://docs.mongodb.org/manual/reference/method/db.collection.update/#db.collection.update ” ... 对于未加密的集合,可以使用$ isolated isolation运算符覆盖此行为,该运算符隔离更新操作并在更新期间阻止其他写入操作。请参见隔离运算符。 ......“

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

此致 Moacy

答案 1 :(得分:0)

是的,find-and-modify将解决您的问题:

db.collection.findAndModify({   查询:{isDone:false},   更新:{$ set:{isDone:true}},   新:真的,   upsert:false#从不创建新文档 });

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

但是如果你的C ++客户端出现打嗝(盒子死了,它们被杀死,代码有错误等等)你就会遇到严重的问题。想象一下,如果你的TCP连接在服务器上更新之后就会丢失,但是在C ++代码获得工作之前。采用多阶段方法通常更好:

  • 将“isDone”更改为“isInProgress”,然后完成后删除文档。 (现在,你可以看到“todo”和“正在完成”的堆栈。如果某些事情已经“完成”很长一段时间,客户可能会死亡。

  • 将“isDone”更改为“phase”并将其从“new”原子设置为“started”(稍后将其设置为“finished”)。现在,您可以看到某些东西是否已“长时间”启动,客户可能已经死亡。

如果你真的很老练,你可以制作部分索引。例如,“只有索引文档有”阶段:{$ ne:'finished'}“。现在你不需要浪费空间索引数百万个已完成的文档。索引只包含少数新的/正在进行的文档,所以它更小/更快。