2

I have multiple servers sharing a common mongodb. In the DB there is a list of jobs, the servers have to finish. As I want to divide the load over all servers and want to avoid multiple servers doing the same job, I want to "Lock" that job.

My Idea is:

  • Set the element as taken if it is not yet taken:

    db.collection.update({done: false, taken: false},{$set: {taken: true, takenBy: myIp}});

  • Check if the server got the mutex on this element: db.collection.findOne({taken: true, takenBy: myIp})

Would that be the best way to "synchronize" multiple worker servers over a mongodb (does the server do updates in a single transaction like mysql) or could the server do multiple of this first commands at once?

4
  • 1
    Possible dupe of stackoverflow.com/questions/9274777/mongodb-as-a-queue-service Commented Sep 23, 2015 at 1:00
  • This question is more about how mongodb encapsulates single queries and updates (in sql they are called transactions) not about how to build a queue (even when it is the goal to build a queue and that was the reason for the question, I want to know how mongod works under the hood) Commented Sep 24, 2015 at 12:53
  • 1
    The short answer is that all updates to a single document are atomic. Have you seen docs.mongodb.org/manual/core/write-operations-atomicity? Commented Sep 24, 2015 at 12:57
  • Thanks, if you write this as an answer, you get an upvote, I searched for transactions but that probably was the wrong wording. Commented Sep 24, 2015 at 13:04

1 Answer 1

4

The key MongoDB feature in this area is that an update to a single document is atomic. From the docs:

In MongoDB, a write operation is atomic on the level of a single document, even if the operation modifies multiple embedded documents within a single document.

When a single write operation modifies multiple documents, the modification of each document is atomic, but the operation as a whole is not atomic and other operations may interleave. However, you can isolate a single write operation that affects multiple documents using the $isolated operator.

So for your update of:

db.collection.update({done: false, taken: false},{$set: {taken: true, takenBy: myIp}}); 

this means that it will atomically find a doc that matches the criteria and then update it. So yes, that will work well to assign a task to a given server.

See this other post for more details on implementing a shared work queue in MongoDB. A key point that's mentioned there is the use of findAndModify to both perform the update and return the updated doc.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.