Nodejs MongoDB Read/Write访问的问题
Nodejs MongoDB Read/Write访问的问题
我设了一组Replication Set 并且读写分离(Primary是写, Secondary是读) 那我在node.js下findAndModify,这指令会修改并回传最新修改后的值, 他会保证回传的值是从Primary吗? 因为Secondary会有延迟的问题,我担心他回传是从Secondary回来 。
之前有看过文档是说Driver会保证同一个事务connection会相同,但对于Replication Set并没有特别解释,这问题也不好测试,请问有人有相关经验吗,谢谢。
Node.js MongoDB Read/Write 访问的问题
问题描述
在设置了一个包含 Primary 和 Secondary 的 Replication Set,并且实现了读写分离(Primary 负责写操作,Secondary 负责读操作)的情况下,当你使用 findAndModify
指令时,该指令会修改并返回最新的修改值。问题是,这个返回的值是否总是从 Primary 获取的?因为 Secondary 可能存在数据延迟的问题,你担心返回的值可能是从 Secondary 获取的。
解释与示例代码
MongoDB 驱动程序在处理读写分离的场景时,通常会确保在一个事务中连接到同一个节点(Primary 或 Secondary)。但是,在涉及 findAndModify
这样的复杂操作时,确保数据的一致性变得更加复杂。
为了确保 findAndModify
始终从 Primary 获取数据,你可以显式地指定连接到 Primary。下面是一个使用 mongodb
驱动程序的示例:
const { MongoClient } = require('mongodb');
async function main() {
const uri = "your_mongodb_connection_string"; // 替换为你的 MongoDB 连接字符串
const client = new MongoClient(uri);
try {
await client.connect();
const database = client.db('your_database_name'); // 替换为你的数据库名称
const collection = database.collection('your_collection_name'); // 替换为你的集合名称
// 显式指定连接到 Primary
const primaryClient = new MongoClient(uri, {
replicaSet: 'your_replica_set_name', // 替换为你的副本集名称
readPreference: 'primary'
});
await primaryClient.connect();
// 使用 findAndModify 操作
const result = await primaryClient.db().collection('your_collection_name').findAndModify(
{ key: 'value' }, // 查找条件
[['_id', 'asc']], // 排序条件
{ $set: { field: 'new_value' } }, // 更新操作
{ new: true } // 返回更新后的文档
);
console.log(result);
} finally {
await client.close();
await primaryClient.close();
}
}
main().catch(console.error);
关键点解释
- 显式连接到 Primary:通过设置
readPreference: 'primary'
,你可以确保连接到 Primary 节点。 - 使用
findAndModify
:这个方法用于查找、修改并返回一个文档。通过传递{ new: true }
参数,可以确保返回的是修改后的文档。 - 关闭连接:在操作完成后,记得关闭客户端连接以释放资源。
通过这种方式,你可以确保 findAndModify
操作总是从 Primary 节点获取最新的数据,避免因 Secondary 节点的数据延迟导致的问题。
测试结果 应该资料会从Primay回来
在使用 MongoDB 的 Replication Set 进行读写分离时,确保 findAndModify
操作从 Primary 节点执行是非常重要的。因为 Secondary 节点可能会有延迟,导致读取的数据不是最新的。
示例代码
你可以通过指定连接字符串中的 readPreference
来确保操作在 Primary 节点上执行。以下是一个示例代码:
const { MongoClient } = require('mongodb');
async function run() {
const uri = "your_mongodb_connection_string";
const client = new MongoClient(uri, {
useNewUrlParser: true,
useUnifiedTopology: true,
readPreference: 'primary' // 确保操作在 Primary 节点上执行
});
try {
await client.connect();
const database = client.db('your_database_name');
const collection = database.collection('your_collection_name');
// 执行 findAndModify 操作
const result = await collection.findAndModify(
{ key: value }, // 查询条件
[], // 排序条件
{ $set: { field: newValue } }, // 更新操作
{ new: true } // 返回更新后的文档
);
console.log(result);
} finally {
await client.close();
}
}
run().catch(console.dir);
解释
-
连接配置:
- 使用
MongoClient
连接到 MongoDB。 - 设置
readPreference: 'primary'
确保所有的读取操作都在 Primary 节点上执行。
- 使用
-
findAndModify 操作:
findAndModify
方法用于查询、修改并返回一个文档。{ new: true }
参数确保返回的是更新后的文档。
通过这种方式,你可以确保 findAndModify
操作总是从 Primary 节点获取数据,从而避免 Secondary 节点的延迟问题。
如果你不希望每次都设置 readPreference
,也可以在创建数据库连接时全局设置:
const client = new MongoClient(uri, {
useNewUrlParser: true,
useUnifiedTopology: true,
readPreference: 'primary'
});
const database = client.db('your_database_name', { readPreference: 'primary' });
这样,整个数据库的所有操作都会默认在 Primary 节点上执行。