处理NodeJSasynchronous行为

使用NodeJS和MongoDB + Mongoose。

首先,我知道asynchronous非阻塞代码的优点。 所以我处理callback。 但最后我遇到了以下问题。

可以说我有一个可以随时被用户调用的函数。 有可能,一个超级“闪电般”的用户几乎在同一时间调用它两次。

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 }) } 

当然,它执行如下:查找查询,查找查询,保存查询,保存查询

这完全打破了应用程序的逻辑(应该查询查询,保存查询,查找查询,保存查询)。 所以我决定通过为特定用户“locking”整个函数来防止asynchronous行为(因此函数代码内部仍然是asynchronous的)。

 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 } } 

所以,我的问题是:这是一个好的做法,好的破解或坏的破解? 如果这是一个不好的破解,请提供任何其他解决scheme。 特别是当我们扩展和启动多个NodeJS进程时,我怀疑这个解决scheme会起作用。

这是一个非常糟糕的做法,你不应该使用定时器来控制代码的stream向。

这里的问题被称为primefaces性。 如果您需要查找保存,find保存,那么您需要以某种方式打包这些操作(事务)。 这取决于你使用的软件。 在redis中你有multi和exec命令。 在MongoDB中你有findAndModify()。 另一个解决scheme是使用索引。 当您尝试两次保存相同的字段时出现错误。 在mongoose的schemaType中使用属性“index:true”和“unique:true”:

 var schema = mongoose.Schema ({ myField: { type: String, index: true, unique: true, required: true }, }); 

这就是你所需要的: Mongodb – 隔离操作顺序 – 执行两阶段提交 。 但是要考虑到,如果你需要做很多交易,mongodb不是最好的select。

你不想浪费内存,所以更换

 lock_function_for_user[user_id] = false 

 delete lock_function_for_user[user_id] 

除此之外: 如果发生冲突 ,您可以保持乐观并重试 。 只要不加锁就可以确保数据库在出现错误时通知(在这种情况下重试)。 当然,哪种方式更好取决于这种冲突发生的频率。