因爲MongoDB不支持事務處理,所以你不能安全地對一批物品進行悲觀鎖定,除非你有一個單獨的文檔 - 更多的在最後。
讓我們從查詢開始:你不能查詢某物。比如'where x + y < z
'在MongoDB中。相反,您必須爲下一個到期日期使用字段,例如nextDue
:
{
"nextDue": "420",
"work": { ... }
}
現在每個工人可以賣到幾個項目的(注:這是所有的僞代碼,而不是特定的編程語言):
var result = db.queue.find({ "nextDue": { $gt, startTime } }).limit(50);
// hint: you can do a random skip here to decrease the chances of collisions
// between workers.
foreach(rover in result)
{
// pessimistic locking: '-1' indicates this is in progress.
// I'd recommend a flag instead, however...
var currentItem = db.queue.findAndModify({ "_id" : rover.id, "nextDue" : {$gt, startTime}}, {$set : {"nextDue" : -1}});
if(currentItem == null)
continue; // hit a lock: another worker is processing this already
// ... process job ...
db.queue.findAndModify({ "_id" : rover.id, "nextDue" : "-1"}, {$set : {"nextDue" : yourNextDue }});
}
主要有兩種方法,我看到悲觀鎖定多個文件。一個是爲您要鎖定的文檔創建存儲桶,將作業描述符放入存儲桶並處理這些存儲桶。從現在開始,這個桶是一個單獨的對象,你可以依賴原子修飾符。
另一個是使用two-phase commit,它也爲交易創建另一個對象,但不要求您將文檔移動到不同的文檔中。但是,這是一個有點複雜的模式。
上面介紹的僞代碼在兩個應用程序中工作得很好,但是在兩個應用程序中,各個作業都花了相當長的時間來執行(半秒到幾個小時)。