简体   繁体   中英

Concurrency in MongoDB

I'm using the collection requests as a queue that multiple clients read from concurrently. Each client will read one document at a time from requests and then remove it from the collection. Can I ensure that each document is read and processed by only 1 client?

The clients are written in Python with pymongo.

The basic procedure here is to use .findAndModify() :

Forgive that this is not python code, but the structure is the same and it's a reasonable universal example. Three documents:

{ "_id": 1 }
{ "_id": 2 }
{ "_id": 3 }

So from the core method, you just call it with the "remove" argument on each _id . No other process can do this at the same time.

db.collection.findAndModify({
    "query": { "_id": 1 },
    "remove": true
})

That will either return the document that was removed or nothing at all.


For a bit more "concurrency" proof, again excuse the node.js code here but I'm not in a frame to do some briliant "Twisted" type code as a quick example. It serves the purpose of a concurrency test though:

var async = require('async'),
    mongoose = require('mongoose'),
    Schema = mongoose.Schema;

var testSchema = new Schema({
  "_id": Number,
});

var Test = mongoose.model( 'Test', testSchema, 'test' );

mongoose.connect('mongodb://localhost/async');

async.series(
  [
    // Clear test collection
    function(callback) {
      Test.remove({},callback)
    },

    // Insert some data
    function(callback) {
      async.each([1,2,3],function(num,callback) {
        Test.create({ "_id": num },callback);
      },callback);
    },

    // Now run test in parallel
    function(callback) {
      async.each([1,1,2,2,3,3],function(num,callback) {
        Test.findOneAndRemove(
          { "_id": num },
          function(err,doc) {
            if (err) callback(err);
            console.log( "Removing: %s, %s", num, doc );
            callback();
          }
        );
      },callback);
    }
  ],
  function(err) {
    process.exit();
  }
);

And results (in possible varying order ) :

Removing: 3, { _id: 3, __v: 0 }
Removing: 1, { _id: 1, __v: 0 }
Removing: 3, null
Removing: 1, null
Removing: 2, { _id: 2, __v: 0 }
Removing: 2, null

So out of the six attempts run here with two attempts per document, only 3 of the attempts actually succeeded and returned the result pulled off of the stack.

That's the principle to ensuring the result you want.

Looks like you're looking for

db.requests.findAndModify()

According to the documentation, if you use this with a unique index on the main field you should end up in a good place.

http://docs.mongodb.org/manual/reference/method/db.collection.findAndModify/

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM