2013-04-13 151 views
4

我的MongoDB集合被用作作業隊列,並且有3個C++機器可以從這個集合中讀取。問題是那三個人不能完成同樣的工作。所有的工作只需要做一次。來自多個客戶端的MongoDB findAndModify

我通過搜索所有記錄'isDone:False'來獲取所有未完成的作業,然後更新此文檔'isDone:True'。但是如果兩臺機器同時找到相同的文件,它們將同時工作。我怎樣才能避免這種情況?

編輯:我的問題是 - findAndModify是否真的解決了這個問題? (閱讀後A way to ensure exclusive reads in MongoDb's findAndModify?

+0

我對你的問題感到困惑。'findAnyModify'的重點在於它可以自動發現並修改文檔爲單一操作,從而避免了這個問題。 – JohnnyHK

+0

我不知道看到http://stackoverflow.com/questions/15505176/a-way-to-ensure-exclusive-reads-in-mongodbs-findandmodify –

+0

@EiTkoCaT http://stackoverflow.com/a /829571分之15539348 – assylias

回答

1

是的,findAndModify解決它。

編號:MongoDB findAndModify from multiple clients 」 ...... 注:此命令獲取受影響的數據庫的寫鎖,將阻塞其他操作,直到它已完成;然而,通常寫鎖是短暫的,相當於其他類似的更新()操作 ......「

編號:http://docs.mongodb.org/manual/reference/method/db.collection.update/#db.collection.update 」 ...... 對於unsharded集合,可以覆蓋與$孤立隔離運營商,這在隔離的更新操作,並阻止其他寫操作這種行爲更新請參閱隔離操作符 ...「

編號:http://docs.mongodb.org/manual/reference/operator/isolated/

問候, Moacy

0

是,查找和修改將解決你的問題:

db.collection.findAndModify({ 查詢:{isDone:假}, 更新:{$ set:{isDone:true}}, new:true, upsert:false#永遠不會創建新文檔 });

這將返回一個文檔,它只是從false更新爲true。

但是,如果您的C++客戶端有呃逆(盒子死亡,他們被殺害,代碼有錯誤等),那麼您會遇到嚴重的問題。想象一下,如果您的TCP連接在服務器更新後立即丟失,但在C++代碼獲得工作之前。多相方式通常更好:

  • 將「isDone」更改爲「isInProgress」,然後在完成時刪除文檔。 (現在,您可以看到「待辦事項」和「正在完成」的堆棧,如果長時間處於「正在進行中」狀態,客戶端可能已經死亡。

  • 將「isDone」更改爲「phase」從設置它的「新」到「開始」(後來將其設置爲「已完成」)。現在你可以看到,如果事情是,客戶端可能已經死亡「開始」很長一段時間。

如果您可以創建一個部分索引,例如,「僅索引文檔的階段:{$ ne:'已完成'}」,現在您不需要浪費索引數百萬個完成文檔的空間。該指數僅保留少量新/正在進行的文件,因此更小/更快。