简体   繁体   中英

Concurrent WriteConflict with MongoDB and NodeJs

I'm creating an application that serves transportation order, while I'm stress testing the application by injecting about 100 orders simultaneously, the mongodb hits WriteConflict due to the numeric sequence id ( nid it is required) that I created using the hook. I have tried to add ?retryWrites=true&w=majority into the connection URI and set those in the transaction level, but none of those work. May I know any parts that I'm missing and should give a try (Knowing that is critical section, and using lock/queue should fix, but want to know any other way)? Thank you very much.

The schema for sequence and order (will keep _id that default created, and mongoose did the thing so haven't mention in the schema)

const SequenceSchema = new Schema<ISequenceDoc>(
  {
    collectionName: {
      type: String,
      trim: true,
      required: true
    },
    nid: {
      type: Number,
      required: true
    }
  },
  {
    collection: 'sequences',
    timestamps: true
  }
);

const OrderSchema = new Schema<IOrderDoc>(
  {
    name: {
      type: String,
      trim: true,
      required: true
    },
    nid: {
      type: Number
    }
  },
  {
    collection: 'orders',
    timestamps: true
  }
);

Pre saving hook to assign an numeric id index of hex id to the schema

OrderSchema.pre('save', async function(next) {
    if (this.isNew) {
      const data = await this.db.model<ISequenceDoc>('Sequence').findOneAndUpdate(
        {
          collectionName: this.collection.collectionName
        },
        {
          $inc: { nid: 1 }
        },
        {
          upsert: true,
          new: true,
          session: this.$session()
        }
      );
      this.set('nid', data.nid);
    }
    next();
});

The code that create the order model and save

async createOrder(orderInfo) => {
const session = await this.connection.startSession();
session.startTransaction({
  readConcern: {
    level: 'majority'
  },
  writeConcern: {
    w: 'majority',
    j: true
  }
});
......
await order.save({session});
await session.commitTransaction();
return order;
}

The problem is that all of your transactions modify the same document in the findOneAndUpdate.

Try acquiring your sequence number before starting the transaction.

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