MST

星途 面试题库

面试题:MongoDB事务与Change Streams协同处理复杂数据关系的策略

假设存在多个集合间复杂的引用关系,在使用MongoDB事务和Change Streams进行实时数据协同过程中,如何确保数据一致性并高效处理跨集合的数据变化,举例说明你的策略。
13.8万 热度难度
数据库MongoDB

知识考点

AI 面试

面试题答案

一键面试

确保数据一致性和高效处理跨集合数据变化的策略

  1. MongoDB事务
    • 原子操作:利用MongoDB事务的原子性,将跨集合的相关操作放在一个事务中。例如,有orders集合和inventory集合,当创建一个新订单时,需要在orders集合插入订单记录,同时在inventory集合减少相应商品的库存。
    const session = client.startSession();
    session.startTransaction();
    try {
        const order = { productId: '123', quantity: 5 };
        await ordersCollection.insertOne(session, order);
        await inventoryCollection.updateOne(
            session,
            { productId: '123' },
            { $inc: { stock: -5 } }
        );
        await session.commitTransaction();
    } catch (error) {
        await session.abortTransaction();
        throw error;
    } finally {
        session.endSession();
    }
    
    • 隔离级别:选择合适的隔离级别。MongoDB提供了read - committed隔离级别,确保事务只能看到已提交的数据更改,防止脏读,有助于维护数据一致性。
  2. Change Streams
    • 基于时间戳的同步:利用Change Streams的startAtOperationTime功能。假设products集合发生变化,我们希望product_reviews集合中的相关评论信息也能实时更新。可以记录products集合变更的时间戳,然后在product_reviews集合的Change Stream中使用这个时间戳作为起点,确保处理的是同一时间点及之后的相关变化。
    const productsStream = productsCollection.watch();
    productsStream.on('change', async (change) => {
        const startAtTime = change.operationTime;
        const reviewsStream = productReviewsCollection.watch([], { startAtOperationTime });
        reviewsStream.on('change', (reviewChange) => {
            // 处理评论集合的变化,确保与产品集合变化关联
        });
    });
    
    • 聚合处理:使用Change Streams的聚合管道,对跨集合的变化进行高效处理。例如,有users集合和user_logs集合,当users集合中用户信息更新时,希望在user_logs集合记录更新日志。可以通过Change Streams的聚合管道直接将users集合的变化信息转化为user_logs集合所需的日志格式并插入。
    const usersStream = usersCollection.watch([
        {
            $match: {
                operationType: { $in: ['update', 'insert', 'delete'] }
            }
        },
        {
            $addFields: {
                logMessage: {
                    $cond: {
                        if: { $eq: ['$operationType', 'insert'] },
                        then: 'User inserted',
                        else: {
                            $cond: {
                                if: { $eq: ['$operationType', 'update'] },
                                then: 'User updated',
                                else: 'User deleted'
                            }
                        }
                    }
                }
            }
        },
        {
            $out: 'user_logs'
        }
    ]);
    
  3. 结合使用
    • 先使用事务确保跨集合操作的原子性和一致性,然后通过Change Streams监听事务提交后的变化,进行进一步的实时数据协同。例如,在上述订单和库存的事务完成后,通过Change Streams监听orders集合的新增订单变化,触发后续的订单处理流程,如发送订单确认邮件等,同时确保与inventory集合库存变化的一致性。