Javascript Meteor:服务器端的Meteor.collections是否会发生竞争情况?

Javascript Meteor:服务器端的Meteor.collections是否会发生竞争情况?,javascript,mongodb,meteor,race-condition,Javascript,Mongodb,Meteor,Race Condition,在my server/server.js中 Meteor.methods({ saveOnServer: function() { var totalCount = Collections.find({ "some": "condition" }).count(); if (totalCount) { var customerId = Collections.update('someId',

在my server/server.js中

Meteor.methods({
    saveOnServer: function() {
        var totalCount = Collections.find({
            "some": "condition"
        }).count();
        if (totalCount) {
            var customerId = Collections.update('someId', {
                "$addToSet": {
                    objects: object
                }
            }, function(err) {
                if (err) {
                    throw err;
                } else {
                    return true;
                }
            });
        } else {}
    }
});
恐怕当两个客户端同时调用saveOnServer()时,它将为每个客户端返回相同的totalCount,并基本上在对象id中插入相同的整数。最终目标是在服务器端使用原子操作插入行,该操作仅在成功返回
totalCount
并插入文档时完成,以确保不存在重复的id?我试图不使用mongodb\u id,而是使用自己的整数递增id列


我想知道如何确保字段在每次插入操作中自动递增?我目前依赖于获取文档的总数。这里可能有比赛条件吗?如果是这样的话,meteor处理这个问题的方法是什么?

在meteor的并发模型中,您可以将整个方法想象为一个不间断的块。为了让Meteor从中途运行一种方法切换到开始另一种方法,你需要“屈服”——该方法需要发出信号,“我可以被打断”

方法在执行异步操作时都会生成,实际上,这意味着在Meteor 0.6.5及更高版本中,任何时候都可以执行数据库更新或使用回调调用方法。由于您给您的
update
调用回调,Meteor将始终尝试在调用
update
update
的回调之间做一些事情。然而,在Meteor 0.6.4.2及更早版本中,无论使用何种回调,数据库更新都是不可中断的

但是,对
saveOnServer
的多次调用将按顺序进行,并且不会导致争用情况。您可以调用
this.unblock()
以允许对
saveOnServer
的多个调用“同时”发生,即,不共享标记为
saveOnServer queue
的不间断数据块的同一队列

给定您拥有的代码,另一种修改
集合的方法可以在调用和更新之间更改
count()
的值

通过实现以下数据模型,可以防止一种方法中途使另一种方法无效:

saveOnServer : function () {
// ...
  Collections.update({_id:someId, initialized:true, collectionCount: {$gt: 0}},
    {$addToSet: {objects: object}});
///...
}
将对象添加到
集合时

insertObject: function() {
//...
  var count = Collections.find({some: condition}).count();
  Collections.insert({_id:someId, initialized:false, collectionCount: count});
  Collections.update({initialized:false},
    {$set:{initialized:true}, $inc: {collectionCount: 1}});
}
请注意,虽然这可能看起来效率低下,但它反映了在不同方法中执行更新和插入所需的确切成本。在
saveOnServer
中不能插入


相反,如果您从
集合中删除回调。update
,则回调将同步发生,并且不会出现Meteor 0.6.5及更高版本的情况。

您可以使此集合在索引字段上具有唯一键,然后按如下方式保持更新:

1) 无论何时插入到集合中,首先执行查询以获取最大索引,然后插入索引为+1的文档

2) 要找出文档的数量,只需执行查询以获得索引的最大值

插入现在是一对查询,一个读取和一个写入,所以它可能会失败。(尽管DB ops总是会失败。)但是,它永远不会让数据库处于不一致的状态——Mongo索引将保证这一点

在Meteor中建立索引的语法如下:

MyCollection._ensureIndex('index', {unique: 1});

另一种方法是使用hibernate/jpa遵循的机制,即设置冲突字段。大多数情况下,这可能是在每次更新时设置的更新时间戳。在执行任何更新之前,查询更新时间戳。然后,您可以指定更新,其中更新时间戳是您刚刚获取的。如果在这段时间内发生了更改,则不会进行更新,并且您将检查返回代码/计数,以确定行是否已更新。
JPA会在您为该碰撞字段添加注释时自动为您执行此操作-但这基本上是它在幕后执行的操作

原则上,meteor代码离数据太远,无法保证这一点。使用dbms工具进行这样的验证是一个更好的主意。在服务器端,一切都是同步的,以避免使用节点光纤的回调地狱?但是meteor.collection管理mongodb,有没有办法保证meteor.collection对象是原子的或无种族条件的?同样的问题也在这里并得到了回答。除非您在多台服务器上运行,否则您的代码不会有问题。新meteor软件包可处理类似问题。它建议不要使用_id这样的字段。只有当您仅使用1台服务器时,才会按顺序执行此操作。如果你有2台以上的服务器,我想你在mongodb写的时候会有竞争条件。检查我的注释以澄清我对Meteor代码的理解。添加了新注释。我关于回调
update
的评论是不准确的,直到0.6.5甚至“同步”数据库操作也让位给其他光纤。在这段时间内,事件循环不会被阻塞-无论您是否提供回调。@AndrewMao那么,您如何确保方法调用按顺序排队和处理?另请看这个关于我现在遇到的类似问题的新问题: