【问题标题】:MongoDB concurrent read-write pairsMongoDB并发读写对
【发布时间】:2020-06-07 15:27:06
【问题描述】:

如何在 MongoDB 中处理并发?

考虑我需要执行 2 次写入的情况,它们本身都是有效的,但我不能同时接受它们。 如果这样的写入同时发生,后面的写入将不会知道前面的写入。

这里我模拟了情况(我使用猫鼬):

const createNew = async () => {

    const session = await mongoose.startSession();
    session.startTransaction();

    const numberOfDocuments = await mongoose.model('User')
        .countDocuments()
        .session(session);

    if(numberOfDocuments > 0) return;    

    const newUser = new mongoose.model('User')();

    newUser.username = 'lol';
    newUser.email = 'lmao';

    await newUser.save(
        {
            session
        }
    );

    await session.commitTransaction();
    session.endSession();

};

createNew();
createNew();

该函数首先检查文档的数量,并且已经有一个,它应该停止。但是,因为它们“同时”执行,所以两个读取都认为文档数为 0,导致插入 2 个文档。

像这样的两个并发请求创建读-读-写-写链,有没有办法确保它是读-写-读-写,并且这个问题有一个通用名称吗?

【问题讨论】:

    标签: mongodb concurrency transactions acid


    【解决方案1】:

    首先,当使用事务时,通常读取也必须在事务下,而不仅仅是写入。这样一来,在发出写入时,读取的数据就不会最终回滚。

    对于您的具体示例,事务在操作之上提供 ACID 属性(尤其是atomicity and consistency)。它们不是互斥的神奇解决方案。我认为事务不会像您尝试做的那样帮助您根据集合大小调整插入。

    MongoDB 不是分布式锁定系统。 Here 是一些软件的列表。

    【讨论】:

    • 是的,你是对的,读取操作超出了事务。我现在修复了代码并再次进行了一些测试,它也不能像这样工作。虽然我的问题不是专门关于交易的。我的问题是如何处理 MongoDB 中描述的情况。我的代码中有事务的原因仅仅是因为这是我解决这个问题的最佳尝试。这是我假设的一个常见问题,两个有效动作同时发生,但是当一个动作发生时,第二个变为无效。如何确保只发生一次?
    • MongoDB 不是分布式锁定系统。 en.wikipedia.org/wiki/Distributed_lock_manager 列出了一些系统。
    • 所以你是说 MongoDB 根本不适合这样的任务?
    • 很可能有一种方法可以在 MongoDB 中实现您的用例。您尝试使用的特定解决方案策略(依赖于全局锁定)似乎不适合 MongoDB。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多