关于mongodb的异步 在Nodejs中的实现
关于mongodb的异步 在Nodejs中的实现
资料上说数据库会为每个连接创建队列,存放这个连接的请求,当客户端发送一个请求会被放到队列的的末尾,只有队列中的的请求都执行完毕后续请求才会执行。这是不是意味这在node里面使用mongodb对于同一个db,两个find请求,第二个find请求在第一个请求的回调函数被执行前是被阻塞的
db.collection('a').find({}, function(){
console.log('a find');
}); //这里的find需要花费10秒钟
db.collection('b').find({}, function(){
console.log('b find');
});//这里的find只需要1秒钟
请问 ‘b find’是在什么时候被打印? 1秒钟还是11秒钟?
关于 MongoDB 的异步在 Node.js 中的实现
在 Node.js 中,MongoDB 的操作是通过异步的方式进行的。这意味着当我们在 Node.js 中调用 MongoDB 的方法时,这些方法不会阻塞程序的执行,而是立即返回并继续执行后续的代码。当操作完成时,会通过回调函数通知你。
示例代码
假设我们有两个查询操作,其中一个查询需要较长时间才能完成(例如10秒),而另一个查询很快就能完成(例如1秒)。以下是示例代码:
const MongoClient = require('mongodb').MongoClient;
// 连接到 MongoDB 数据库
MongoClient.connect('mongodb://localhost:27017/mydatabase', (err, client) => {
if (err) {
console.error(err);
return;
}
const db = client.db();
// 第一个查询,需要10秒钟
db.collection('a').find({}).toArray((err, docs) => {
if (err) {
console.error(err);
return;
}
console.log('a find:', docs.length); // 假设 a 表有大量数据
});
// 第二个查询,只需要1秒钟
db.collection('b').find({}).toArray((err, docs) => {
if (err) {
console.error(err);
return;
}
console.log('b find:', docs.length); // 假设 b 表数据较少
});
// 注意:这里的输出顺序不能保证
});
输出时间
在这个例子中,'b find'
会在大约1秒钟后被打印出来,而不是等待 'a find'
完成后再打印。即使 'a find'
需要10秒钟才能完成,'b find'
也会在第一个查询开始后的1秒钟左右被打印。
解释
-
异步非阻塞:Node.js 和 MongoDB 驱动程序都是异步非阻塞的。这意味着当你的代码调用
find
方法时,它会立即返回,不会等待查询结果。 -
事件循环:Node.js 使用事件循环来处理异步操作。当你调用
find
方法时,它会被放入事件循环中,同时你的代码会继续执行。当查询完成后,MongoDB 驱动程序会触发相应的回调函数。 -
并发性:多个查询可以并发执行,而不必等待前一个查询完成。因此,
'b find'
不会被阻塞,而是在第二个查询完成后立即执行其回调函数。
总结来说,在 Node.js 中使用 MongoDB 时,你可以充分利用异步特性来实现高效的并发操作。'b find'
会在大约1秒钟后被打印出来,而不是等待 'a find'
完成后再打印。
先到先得 你的代码其实就是2行,对于解析器来说,都会被解析到异步队列里面。进入队列后就开始执行,谁最先执行出来就先打印谁的。
貌似没理解我的含义, mogodb并发执行这两个请求,'b find’应该在1秒钟左右被打印出来,但如果mongodb没有并发之行这个请求呢?
我感觉没必要纠结这个,如果你觉得真有必要,就自己做个测试好了
我感觉有必要,这涉及到要不要使用连接池,如果是并发的话程序里只要维护一个连接就可以了,现在主要是没有好的数据库可以测试,无法模拟出效果来
做了简单的测试,是按顺序的,有待进一步测试 http://inosql.org/topic/5135bcd4fd6181f36806ea4b
我也测试了,是按顺序的,所以同一个连接并不是并发请求的
本以为凭借node的异步一个程序里维护一个mongodb的连接就够了的想法是错的,还是得使用连接池
在Node.js中,MongoDB驱动程序实现了非阻塞IO模型。因此,即使在内部存在请求队列的概念,每个请求仍然是异步处理的,并且不会互相阻塞。
在这个例子中:
db.collection('a').find({}, function() {
console.log('a find');
}); // 这里的find需要花费10秒钟
db.collection('b').find({}, function() {
console.log('b find');
}); // 这里的find只需要1秒钟
'b find'
会在大约1秒钟后被打印,而不是11秒钟。因为这两个操作是异步的,所以它们几乎同时开始。'b find'
将在它自己的回调函数被执行时打印,而不会等待'a find'
的回调函数执行完成。
为了验证这一点,可以稍微修改代码以输出时间戳:
console.time('a');
db.collection('a').find({}).toArray(function(err, result) {
console.timeEnd('a');
console.log('a find', new Date().toISOString());
});
console.time('b');
db.collection('b').find({}).toArray(function(err, result) {
console.timeEnd('b');
console.log('b find', new Date().toISOString());
});
这段代码将打印出两个查询的时间戳,帮助我们理解它们的实际执行情况。通常情况下,这两个查询的结果会非常接近,尽管第一个查询可能会稍微慢一些。