多个用户同时发送请求时的异常行为

多个用户同时发送请求时的异常行为

本文介绍了NodeJS和Mongo-多个用户同时发送请求时的异常行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们一直在使用NodeJS和mongo(通过mongoose)来做一个非常简单的save().我们有一个名为"highlights"的模型,其中包含一个引用"responss"的ObjectId数组.

We've been using NodeJS and mongo (via mongoose) to do a very simple save(). We have a model called "highlights" which contains an array of ObjectId s that reference "responses."

这是突出显示模型声明的相关部分

This is the relevant segment of the highlight model declaration

var highlightSchema = Schema({
  [...]
  , responses: [{type: ObjectId, ref: 'Response'}]
  [...]
});

我们先将响应插入到突出显示中,方法是先保存一个响应对象,然后将其推入突出显示对象,然后保存突出显示对象.非常简单,如下所示:

We insert a Response into a Highlight by first saving a Response object, then pushing it into an a Highlight object, and then saving the Highlight object. Very straightforward, as follows:

      Highlight.findOne({[...]}, function(err, highlight) {
        var response = new Response({[...]});
        response.save(function(err) {
          if(!err) {
            highlight.responses.push(response)
            highlight.save(function(err) {
              [...]
            })
          }
        });
      });

这完全可以按预期运行99%以上的时间. (注意:您可以放心地假设上述代码中的"highlight"变量确实包含有效的Highlight对象)

This works about 99%+ of the time exactly as expected. (note: you can safely assume that the 'highlight' variable in the above code does contain a valid Highlight object)

但是,由于许多确切的请求是同时发出的,因此我们在高峰时段越来越遇到孤立的问题.在一种情况下,成功创建了一个响应,但是将一个不同的响应推入了highlight.responses数组.

However, we are increasingly experiencing isolated problems during peak hours as many of this exact request is made simultaneously. In one case, a Response was created successfully, but a DIFFERENT Response was pushed into the highlight.responses array.

这两个响应的时间戳表明它们的创建间隔约为30毫秒.除了Highlight对象中数组内容之外,所有内容均按预期创建.

The timestamps of those two Responses showed that they were created about 30 milliseconds apart. Everything was created exactly as expected, except for the contents of the arrays inside the Highlight objects.

由于我目前也正在研究许多操作系统,因此我首先想到的是这可能与某种类型的同步有关.但是node是单线程的,我不觉得我对nodejs的事件循环的工作原理有很好的了解,甚至我也不完全相信这首先就是问题所在.

Since I'm currently also delving into a lot of operating systems stuff, my first thought was that this could be an issue with synchronization of some kind. But node is single-threaded, and I don't feel like I have a very good understanding of how nodejs's event loop works, nor am I even completely confident that that is the issue in the first place.

如果您有任何想法,或者我对此解释是否足够清楚,请告诉我.我很高兴阐述.

Please let me know if you have any ideas, or if I am explaining this clearly enough. I'm happy to elaborate.

谢谢!

推荐答案

您遇到了并发问题.模式的建模方式不能确保原子性,因此不能确保您遇到的问题.

You're running into a concurrency issue. The way you have your schemas modeled will not ensure atomicity, hence the issues you're experiencing.

避免此类问题并确保原子性的最佳选择是将Responses模型嵌套到Highlights模型中.

The best option to avoid such problems and to ensure atomicity, would be to nest the Responses model into the Highlights model.

这样,通过将Response元素直接推到Highlight模型的Responses属性中,您将只能使用Highlights模型.

This way you'd be working only with the Highlights model by pushing a Response element directly into the Responses property of the Highlight model.

这是确保MongoDB原子性的唯一方法.

This is the only way to ensure atomicity with MongoDB.

所以您会遇到类似这样的事情:

So you'd have something like this:

   +----------------------+
   |  Highlight model     |
   +----------------------+
   | _id 1                |
   |                      |
   | property 1: 'abc'    |
   | property 2: 'bla'    |
   | property 3: 123      |
   | responses:[          |
   |   +----------------+ |
   |   | Response _id 1 | |
   |   +----------------+,|
   |   | Response _id 2 | |
   |   +----------------+,|
   |   | Response _id 3 | |
   |   +----------------+,|
   |   | Response _id n | |
   |   +----------------+]|
   +----------------------+

不确定如何使用Mongoose,但是在mongo shell中,如果要使用_id ObjectId('1234')添加对Highlight对象的响应,则可以执行以下操作:

Not sure how you do it with Mongoose, but in the mongo shell if you wanted to add a response to the Highlight object with _id ObjectId('1234') you'd do something like this:

    db.highlights.update({_id: ObjectId('1234')},{$push:{Responses: {"Your response object"}}});

来自MongoDB文档的$ push参考

我很确定您必须能够以一种更简单的方式用Mongoose完成此操作,可能只是浏览其文档即可.

I'm pretty sure that you must be able to acomplish this with Mongoose in a simpler way, probably just a matter of browsing it's documentation.

这篇关于NodeJS和Mongo-多个用户同时发送请求时的异常行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-20 16:52