【问题标题】:How to solve meeting room booking conflict problem in MongoDB?如何解决MongoDB中的会议室预订冲突问题?
【发布时间】:2021-08-19 21:22:03
【问题描述】:

在使用 RDBMS 实现一个典型的会议室预订系统时,会有两个操作:

-- Check for any existing bookings that overlap with the period of noon-1pm
SELECT COUNT(*) FROM bookings WHERE room_id = 123 AND
end_time > '2015-01-01 12:00' AND start_time < '2015-01-01 13:00';

-- If the previous query returned zero:
INSERT INTO bookings
(room_id, start_time, end_time, user_id)
VALUES (123, '2015-01-01 12:00', '2015-01-01 13:00', 666);

代码来自:设计数据密集型应用程序(第 249 页)-- Martin Kleppmann

我们需要将隔离级别设置为可序列化,以避免两个用户认为没有冲突并插入两个冲突预订的情况。

我的问题是:

假设我们将每个预订时间段建模为一个文档,我们如何在 MongoDB 中实现一个可以避免冲突预订的系统?

  • 我比较好奇MongoDB是如何处理并发事务的。

  • 假设我想允许用户预订任何可能的时间段,而不仅仅是预定义的时间段。

  • 假设用户A想预订时间段T1,B想预订时间段T2T1T2强>相互重叠。很有可能两个用户同时进入预约页面,通过 MongoDB 查询并没有发现冲突,他们都决定将两个相互冲突的时间段插入 DB。

  • 在RDBMS中,我们设置了隔离级别来解决这个问题,那么MongoDB呢?

【问题讨论】:

  • And we'll need to set the isolation level to serializable 是什么意思?
  • @MuratColyaran 在 RDBMS 中,我们使用隔离级别来控制并发事务如何相互影响。在这种情况下,必须使用可序列化。
  • 嘿@JohntheTraveler,你找到解决方案了吗?我正在尝试解决类似的问题。

标签: mongodb


【解决方案1】:

它是原子的,当您对文档执行操作时。 Mongo 中有一些事务,就像 SQL 一样。

这可能会有所帮助; https://docs.mongodb.com/manual/core/transactions/

【讨论】:

  • 但是在这里我做了两个操作: 1. 检查 mongoDB 中是否有冲突的预订(文档) 2. 如果没有,则将预订(新文档)插入 mongoDB 我想这两个操作不是原子的?
【解决方案2】:

我不太确定And we'll need to set the isolation level to serializable 是什么意思,但我会添加一个额外的层,当用户在预订之前在两个日期之间进行选择时发送请求。

所以,在 API 方面。您必须有一个返回预订日期和选定日期的列表端点。

F.e:

{
    "reservations": [
        {
            "userId": "1234567",
            "startDate": "19-08-2021",
            "endDate": "22-08-2021"
        }
        ...
    ]
}

在前端,您可以显示startDateendDates 之间的日期被占用。 当用户在两个日期之间进行选择时,您可以发送具有所选日期的请求。

f.e 端点是 POST /reservations/{roomId}/selected

然后,您可以将房间标记为选中 300 秒。

[
    {
        "roomId": "1234456",
        "selected": true,
        "booked": false
    }
    ...
]

当用户支付房间或其他东西时。您可以标记已预订的房间

[
    {
        "roomId": "1234456",
        "selected": false,
        "booked": true
    }
    ...
]

如果用户在那 300 秒内没有付款,您可以将他重定向到主屏幕。并再次标记房间booked: false

编辑:

在编写分析器时,我不确定isolation level 是什么。但正如我给你的例子,我认为你可以使用相同的系统。您可以标记房间selected: true,直到付款完成

【讨论】:

  • 谢谢,不过我比较好奇MongoDB是如何处理并发事务的。假设我想允许用户预订任何可能的时间段,而不仅仅是您设计中的预定义时间段。假设用户A要预订时隙T1,B要预订时隙T2,T1和T2相互重叠。很有可能两个用户同时到达预约页面,通过查询MongoDB没有发现冲突,他们都将两个相互冲突的时间段插入到DB中。在RDBMS中,我们设置了隔离级别来解决这个问题,那么MongoDB呢?
  • @JohntheTraveler 如果您在前端实现了一个附加层,并标记您选择的房间或您不必担心冲突的东西。因为您可以在将用户重定向到付款屏幕之前检查用户是否选择了房间。您所说的方法也可以,但您必须创建一个新的集合、模型和许多其他东西。您还必须计算每个月的日期。这是很多工作。
猜你喜欢
  • 2022-08-05
  • 1970-01-01
  • 1970-01-01
  • 2012-07-27
  • 2012-07-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多