我的MongoDB集合用作作业队列,有3个C ++计算机可以从这个集合中读取。问题是那三个人不能完成同样的工作。所有工作只需要进行一次。
我通过使用'isDone:False'搜索集合中的所有记录来获取所有未完成的作业,然后更新此文档'isDone:True'。但是,如果2台机器同时找到相同的文档,那么它们都会完成相同的工作。我怎么能避免这个?
编辑:我的问题是 - findAndModify真的能解决这个问题吗? (阅读A way to ensure exclusive reads in MongoDb's findAndModify?)
之后答案 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'}“。现在你不需要浪费空间索引数百万个已完成的文档。索引只包含少数新的/正在进行的文档,所以它更小/更快。