Node.js 与MongoDB和NodeJs并发写冲突

Node.js 与MongoDB和NodeJs并发写冲突,node.js,mongodb,mongoose,Node.js,Mongodb,Mongoose,我正在创建一个服务于运输订单的应用程序,同时通过同时注入大约100个订单来对应用程序进行压力测试,mongodb由于我使用钩子创建的数字序列id(nid它是必需的)而点击WriteConflict。我曾尝试将?retryWrites=true&w=mailty添加到连接URI中,并在事务级别设置这些URI,但这些都不起作用。我是否可以知道我缺少的任何部分,并应该尝试一下(知道这是关键部分,使用锁/队列应该修复,但想知道其他方法)?多谢各位 序列和顺序的模式(将保留默认创建的_id,mongoos

我正在创建一个服务于运输订单的应用程序,同时通过同时注入大约100个订单来对应用程序进行压力测试,mongodb由于我使用钩子创建的数字序列id(nid它是必需的)而点击WriteConflict。我曾尝试将
?retryWrites=true&w=mailty
添加到连接URI中,并在事务级别设置这些URI,但这些都不起作用。我是否可以知道我缺少的任何部分,并应该尝试一下(知道这是关键部分,使用锁/队列应该修复,但想知道其他方法)?多谢各位

序列和顺序的模式(将保留默认创建的_id,mongoose做了模式中没有提到的事情)


问题是您的所有事务都会修改findOneAndUpdate中的同一文档


在开始交易之前,请尝试获取序列号。

但缺点是它们不在同一交易中,这可能导致全部或全部失败。将它们保留在同一交易中会导致失败。不能让同步事务更新同一文档。只有一个会成功,其余的需要重试。如果事务在获取nid后失败,您可以保留相同的nid以供重试,或者将其记录为失败的事务并获取新的nid以供重试。只有当您准备一次只有一个事务进程时,才能在事务中获取它。
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
  }
);
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();
});
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;
}