Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/41.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Node.js 来自多个进程的Mongodb查询;如何实现原子性?_Node.js_Mongodb_Mongoose_Atomicity - Fatal编程技术网

Node.js 来自多个进程的Mongodb查询;如何实现原子性?

Node.js 来自多个进程的Mongodb查询;如何实现原子性?,node.js,mongodb,mongoose,atomicity,Node.js,Mongodb,Mongoose,Atomicity,我有一个mongodb数据库,其中多个节点处理读写文档。我想知道如何做到这一点,以便一次只能处理一个文档。(某种类型的锁定)在进程完成更新该条目后释放 我的应用程序应执行以下操作: 用光标逐一浏览每个条目 (锁定该条目,以便其他进程无法使用它) 从第三方网站获取信息 计算新信息并更新条目 (解锁文档) 此外,在解锁文档后,在几个小时内不需要其他流程对其进行更新 稍后,我想设置多个mongodb集群,以便减少数据库上的负载。因此,该解决方案应同时适用于单个和多个数据库服务器。或者至少使用多个m

我有一个mongodb数据库,其中多个节点处理读写文档。我想知道如何做到这一点,以便一次只能处理一个文档。(某种类型的锁定)在进程完成更新该条目后释放

我的应用程序应执行以下操作:

  • 用光标逐一浏览每个条目
  • (锁定该条目,以便其他进程无法使用它)

  • 从第三方网站获取信息

  • 计算新信息并更新条目
  • (解锁文档)
此外,在解锁文档后,在几个小时内不需要其他流程对其进行更新

稍后,我想设置多个mongodb集群,以便减少数据库上的负载。因此,该解决方案应同时适用于单个和多个数据库服务器。或者至少使用多个mongo服务器。

根据:
隔离:防止影响多个文档的写入操作在写入第一个文档后屈服于其他读取或写入操作$隔离运算符使写入操作获取集合的独占锁…将使WiredTiger在操作期间成为单线程。
因此,如果要更新多个文档,可以首先从第三方API获取数据,例如将信息解析为数组,然后在Mongo shell中使用类似的内容:

db.foo.update(
    { status : "A" , $isolated : 1 },
    { $set: { < your key >: < your info >}}, //use the info in your array
    { multi: true }
)
db.foo.update(
{状态:“A”,$isolated:1},
{$set:{},//使用数组中的信息
{multi:true}
)
或者,如果必须逐个更新文档,可以使用MongoDB节点驱动程序的findAndModify()或updateOne()。请注意,根据“修改单个文档时,findAndModify()和update()方法都会自动更新文档。”

一个逐个更新的示例:首先获取并解析数据,然后再将数据用于,如下所示:

var request = require('request');

var MongoClient = require('mongodb').MongoClient,
    test = require('assert');

MongoClient.connect('mongodb://localhost:27017/test', function(err, db) {
    var collection = db.collection('simple_query');
    collection.find().forEach(
        function(doc) {
            request('http://www.google.com', function(error, response, body) {
                console.log('body:', body); // parse body for your info
                collection.findAndModify({
                    <query based on your doc>
                }, {
                    $set: { < your key >: < your info >
                    }
                })
            });
        }, function(err) {
        });
    });
var request=require('request');
var MongoClient=require('mongodb')。MongoClient,
测试=要求(“断言”);
MongoClient.connect('mongodb://localhost:27017/test,函数(err,db){
var collection=db.collection('simple_query');
collection.find().forEach(
功能(doc){
请求('http://www.google.com,函数(错误、响应、正文){
console.log('body:',body);//解析body以获取您的信息
collection.findAndModify({
}, {
$set:{
}
})
});
},函数(err){
});
});

一个不涉及锁的优雅解决方案是:

  • 版本
    属性添加到文档中

  • 更新文档时,增加
    version
    属性

  • 更新文档时,在查找查询中包括上次读取的
    版本
    。如果您的文档已在其他地方更新,则“查找”查询将不会产生任何结果,并且更新将失败

  • 如果更新失败,可以重试该操作

我过去曾成功地使用过这种模式

例子 假设您有一个文档
{u id:123,版本:1}

想象一下,现在有3个Mongo客户端正在执行
db.collection.findAndModify({query:{u id:123,version:1},update:{$inc:1}),同时执行


第一次更新将应用,其余更新将失败。为什么?因为现在的
version
2
,并且
查询包含
version:1

,您需要在应用层上实现。您能详细说明这个问题并发布一个答案吗?对不起,没有什么需要详细说明的。Mongodb不支持事务,所以您需要自己实现它,或者使用一个npm包。前者对于StackOverflow格式来说过于宽泛,而后者则相当固执己见,因为它们的数量相当多。如果您尝试其中一个软件包,并且遇到一些编码问题,这将是一个更合适的问题。感谢您,我认为如果没有事务,还有一种替代方法可以使我的节点应用程序在某些情况下无法在相同的任务上工作。原因我不明白为什么我的问题太宽泛:)在一句话中,我只是问:如何使我的节点进程不在mongodb中存储为文档的相同任务上工作。应用程序级锁定是另一种选择。谢谢,到目前为止,我真的不明白这是如何工作的。现在,我设法从第三方应用程序(web应用程序)中为流程逐个分配任务。在等待答案的同时,还对应用程序进行了大量优化,看起来有必要进行一段时间的扩展。不管怎样,你能再详细解释一下答案吗?谢谢。也许可以用一个简单的查找和更新来展示一个例子?因为我的应用程序实际上就是这么做的。如果您提供有关文档和API的详细信息,示例可能会更具体。这在设置为复制的多个数据库服务器上如何工作?这与仅为每个文档设置布尔值有什么不同?(bool WorkingOnIt;)然后它被复制到第二个数据库服务器,但另一个进程正在从该服务器读取数据,并且它已经开始执行任务,但它不应该执行。我不知道是谁以及为什么对答案投了赞成票。请详细说明为什么这是一个解决方案,以及它如何使用此解决方案在复制服务器上工作,成功的第一次更新将使其余更新无效。让我将其添加到响应中。复制对客户端是透明的,因此它不相关。复制会跨服务器传播数据库日志。您唯一需要担心的是mongo在哪个级别应用锁。在本例中,从最新的mongo版本开始,mongo将在文档位置应用锁