Nodejs MongoDB Read/Write访问的问题

Nodejs MongoDB Read/Write访问的问题

我设了一组Replication Set 并且读写分离(Primary是写, Secondary是读) 那我在node.js下findAndModify,这指令会修改并回传最新修改后的值, 他会保证回传的值是从Primary吗? 因为Secondary会有延迟的问题,我担心他回传是从Secondary回来 。

之前有看过文档是说Driver会保证同一个事务connection会相同,但对于Replication Set并没有特别解释,这问题也不好测试,请问有人有相关经验吗,谢谢。

3 回复

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);

关键点解释

  1. 显式连接到 Primary:通过设置 readPreference: 'primary',你可以确保连接到 Primary 节点。
  2. 使用 findAndModify:这个方法用于查找、修改并返回一个文档。通过传递 { new: true } 参数,可以确保返回的是修改后的文档。
  3. 关闭连接:在操作完成后,记得关闭客户端连接以释放资源。

通过这种方式,你可以确保 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);

解释

  1. 连接配置

    • 使用 MongoClient 连接到 MongoDB。
    • 设置 readPreference: 'primary' 确保所有的读取操作都在 Primary 节点上执行。
  2. 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 节点上执行。

回到顶部