将NodeJS与MongoDB + Mongoose结合使用。
首先,我知道异步非阻塞代码的优点。所以我确实处理回调。但是最后我遇到了以下问题。
可以说我有一个可以随时被用户调用的函数。超级“闪电般的”用户可能几乎同时调用两次。
function do_something_with_user(user_id){ User.findOne({_id:user_id}).exec(function(err,user){ // FIND QUERY // Do a lot of different stuff with user // I just cannot update user with a single query // I might need here to execute any other MongoDB queries // So this code is a set of queries-callbacks user.save() // SAVE QUERY }) }
当然它是这样执行的:查找查询,查找查询,保存查询,保存查询
这完全破坏了应用程序的逻辑(应查找查询,保存查询,查找查询,保存查询)。因此,我决定通过“锁定”特定用户的整个功能来防止异步行为(因此功能代码内部仍是异步的)。
var lock_function_for_user = {} function do_something_with_user(user_id){ if(!lock_function_for_user[user_id]){ lock_function_for_user[user_id] = true User.findOne({_id:user_id}).exec(function(err,user){ // Same code as above user.save(function(){ lock_function_for_user[user_id] = false }) }) } else { setTimeout(function(){ do_something_with_user(user_id) },100) // assuming that average function execution time is 100ms in average } }
所以,我的问题是:这是一种好的做法,是好的还是好的?如果是骇客,请提供其他解决方案。特别是,我怀疑这种解决方案在我们扩展和启动多个NodeJS流程时是否会起作用。
这是一个非常糟糕的做法,永远不要使用计时器来控制代码流。
这里的问题称为原子性。如果需要执行find-save,find- save,则需要以某种方式打包这些操作(事务)。这取决于您使用的软件。在redis中,您具有multi和exec命令。在mongodb中,您具有findAndModify()。另一种解决方案是使用索引。当您尝试保存同一字段两次时,您将收到一个错误。在猫鼬的schemaType中使用属性“ index:true”和“ unique:true”:
var schema = mongoose.Schema ({ myField: { type: String, index: true, unique: true, required: true }, });
这就是您所需要的:Mongodb-隔离操作序列- 执行两阶段提交。但是要考虑到,如果您需要进行大量事务,mongodb可能不是最佳选择。