Node.js 与MongoDB和NodeJs并发写冲突
我正在创建一个服务于运输订单的应用程序,同时通过同时注入大约100个订单来对应用程序进行压力测试,mongodb由于我使用钩子创建的数字序列id(nid它是必需的)而点击WriteConflict。我曾尝试将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
?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;
}