7

在我的服务器/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 {}
    }
});

恐怕当 2 个客户端同时调用 saveOnServer() 时,它会为每个客户端返回相同的 totalCount 并且基本上最终将相同的整数插入到对象 id 中。最终目标是使用原子操作在服务器端插入行,该原子操作仅在totalCount成功返回并插入文档时完成,以确保不存在重复的 id?我试图不使用 mongodb _id 但有我自己的整数递增 id 列。

我想知道如何确保每个插入操作的字段自动递增?我目前依靠获取文件总数。这里可能存在竞争条件吗?如果是这样,流星的处理方式是什么?

4

3 回答 3

9

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

方法在执行异步操作时会产生,这实际上意味着在 Meteor 0.6.5 及更高版本中进行数据库更新或使用回调调用方法时。由于你给你的update调用一个回调,Meteor总是会尝试在调用updateupdate回调之间做一些事情。但是,在 Meteor 0.6.4.2 和更早版本中,无论使用回调,数据库更新都不会中断。

但是,多次调用saveOnServer将按顺序发生,不会导致竞争条件。您可以调用this.unblock()以允许多个调用saveOnServer“同时”发生——即,不共享同一队列,标记为saveOnServer queue,不间断的东西块。

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

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

saveOnServer : function () {
// ...
  Collections.update({_id:someId, initialized:true, collectionCount: {$gt: 0}},
    {$addToSet: {objects: object}});
///...
}

添加对象时Collections

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你不能插入。

相反,如果您从 中删除回调Collections.update,它将同步发生,并且不会有竞争条件 Meteor 0.6.5 及更高版本。

于 2013-08-08T06:01:13.803 回答
1

您可以使该集合在索引字段上具有唯一键,然后按如下方式对其进行更新:

1)每当您插入集合时,首先进行查询以获取最大索引并插入索引+ 1的文档。

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

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

在 Meteor 中建立索引的语法是这样的:

MyCollection._ensureIndex('index', {unique: 1});
于 2013-08-12T07:40:47.230 回答
1

另一种方法是通过 hibernate/jpa 遵循的机制——即设置一个碰撞场。大多数情况下,这可以是在每次更新时设置的更新时间戳。在进行任何更新之前,请查询更新时间戳。然后您可以指定更新,其中更新时间戳就是您刚刚获取的内容。如果它在过渡期间发生了变化,则不会发生更新 - 您检查该行是否更新的返回代码/计数。当您为此碰撞字段添加注释时,JPA 会自动为您执行此操作 - 但这本质上是它在幕后所做的

于 2017-03-20T23:28:57.007 回答