Как решить проблему конфликта бронирования конференц-залов в MongoDB?

#mongodb

Вопрос:

При внедрении типичной системы бронирования конференц-залов с использованием СУБД будут выполняться две операции:

 -- 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) — Мартин Клеппманн

И нам нужно будет установить уровень изоляции на сериализуемый, чтобы избежать случая, когда два пользователя думают, что конфликтов нет, и вставляют два конфликтующих бронирования.

Мой вопрос таков:

Предполагая, что мы моделируем каждый интервал времени бронирования как документ, как мы реализуем систему, которая может избежать конфликтных бронирований в MongoDB?

  • Мне больше любопытно, как MongoDB обрабатывает параллельные транзакции.
  • Допустим, я хочу разрешить пользователям бронировать любой возможный временной интервал, а не только заранее определенный временной интервал.
  • Предположим, пользователь A хочет забронировать временной интервал T1, а B хочет забронировать временной интервал T2, и T1 и T2 перекрываются друг с другом. Очень возможно, что два пользователя одновременно перейдут на страницы бронирования, проверят MongoDB и не обнаружат конфликтов, и они оба решат вставить два временных интервала, которые конфликтуют друг с другом, в базу данных.
  • В СУБД мы устанавливаем уровень изоляции для решения этой проблемы, как насчет MongoDB?

Комментарии:

1. Что вы имеете в виду под And we'll need to set the isolation level to serializable этим ?

2. @MuratColyaran В СУБД мы используем уровень изоляции для контроля того, как параллельные транзакции влияют друг на друга. и в этом случае необходимо использовать сериализуемый.

Ответ №1:

Это атомарно, когда вы выполняете операцию над документом. В Монго есть транзакции, подобные тем, что есть в SQL.

Это может быть полезно; https://docs.mongodb.com/manual/core/transactions/

Комментарии:

1. но здесь я выполняю две операции: 1. проверьте, есть ли конфликтующие заказы (документы) в MongoDB 2. если нет, то вставьте бронирование (новый документ) в MongoDB Я полагаю, что эти две операции не являются атомарными?

Ответ №2:

Я не совсем уверен, что вы имеете And we'll need to set the isolation level to serializable в виду, но я бы добавил дополнительный слой, который отправляет запрос, когда пользователь выбирает между двумя датами перед бронированием.

Итак, на стороне API. У вас должна быть конечная точка списка, которая возвращает забронированные и выбранные даты.

Ф. е:

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

А на лицевой стороне вы можете показать даты между startDate и endDates занятыми.
И когда пользователь выбирает между двумя датами, вы можете отправить запрос с выбранными датами.

например, конечная точка-это СООБЩЕНИЕ /reservations/{roomId}/selected

Затем вы можете пометить комнату как выбранную, например, на 300 секунд.

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

Когда пользователь заплатил за номер или что-то в этом роде. Вы можете отметить забронированный номер

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

Если пользователь не произвел платеж за эти 300 секунд, вы можете перенаправить его на главный экран. И booked: false снова пометьте комнату.

Редактировать:

Я не был уверен, что происходит isolation level во время написания анализатора. Но поскольку я привожу вам пример, я думаю, что вы можете использовать ту же систему. Вы можете пометить номер selected: true до тех пор, пока не будет произведена оплата

Комментарии:

1. Спасибо, но мне больше интересно, как MongoDB обрабатывает параллельные транзакции. Допустим, я хочу разрешить пользователям бронировать любой возможный временной интервал, а не только предопределенные временные интервалы, как в вашем дизайне. Предположим, пользователь A хочет забронировать временной интервал T1, а B хочет забронировать временной интервал T2, и T1 и T2 перекрываются друг с другом. Очень возможно, что два пользователя одновременно попадают на страницы бронирования и не обнаруживают конфликтов, запрашивая MongoDB, и оба они вставляют два временных интервала, которые конфликтуют друг с другом, в базу данных. В СУБД мы устанавливаем уровень изоляции для решения этой проблемы, как насчет MongoDB?

2. @JohntheTraveler Если вы добавите дополнительный слой в свой интерфейс и отметите выбранную комнату или что-то еще, вам не нужно беспокоиться о конфликтах. Потому что вы сможете проверить, выбрал ли пользователь номер, прежде чем перенаправлять его на экран оплаты.. Метод, о котором вы говорите, также может работать, но вам нужно создать новую коллекцию, модель и многое другое. Вам также нужно будет рассчитать даты в каждом месяце.. Это большая работа.