Как система бронирования мест в кинотеатре не позволяет нескольким пользователям бронировать одни и те же места?


34

В кинотеатре я иду к билетным киоскам, которые позволяют вам выбрать нужные места; у них также есть веб-сайт, который делает то же самое (веб-сайт также имеет таймер обратного отсчета около 30 секунд, в течение которого вы должны выбрать место).

Хотя я понимаю такие вещи, как транзакции с базой данных и другие методы работы с несколькими одновременными пользователями, я просто не могу понять, как нескольким людям может быть разрешено выбирать место одновременно; это так же просто, как первый, кто нажмет «КУПИТЬ», получит места, а другой получит сообщение об ошибке, или я что-то упустил?


10
«это так же просто, как первый, кто нажмет« КУПИТЬ », получит места, а другой получит сообщение об ошибке». Что.
Яннис

2
Да, наверное, в деловой день с дюжиной машин кажется, что это будет больно.
mbwasi

2
Возможно, но имейте в виду, что пользователи будут проводить большую часть своего времени на других экранах (ввод платежных данных, ожидание распечатки билетов и т. Д.), Поэтому они не будут одновременно выбирать места, и не у всех одинаковые предпочтения мест, поэтому даже те, кто выбирают в одно и то же время, скорее всего, выберут разные места. Я не ожидал, что там будет столько столкновений.
Дейв Шерохман

2
@JimG. Для каждого возможного решения, если оба клиента нажмут на покупку в одно и то же время (с точностью до миллисекунды), один получит обслуживание, а другой получит какое-то сообщение об ошибке. Есть прекрасные способы минимизировать вероятность этого (техническая и концептуальная, как объяснено в ответах), но в неординарной ситуации это происходит, когда один запрос будет обработан, а другой потерпит неудачу. Так просто, как, что.
Яннис

3
@JimG. Это не тип поведения. Параллелизм работает до определенного момента, если оба запроса достигают в одно и то же время, один из них не будет выполнен. Конечно, вы можете создать хорошее сообщение об ошибке, как в комментарии Hand-E-Food, но факт остается фактом: это так же просто, как обслуживать один запрос и не выполнять другой. Я не говорю, что вы не должны делать все для того, чтобы сбой был настолько удобным для пользователя, насколько это возможно, или чтобы вы не защищали его.
Яннис

Ответы:


27

Классический метод сделать это - использовать транзакционную базу данных (чтобы не было конфликтов) и предварительно назначить место, срок действия которого истекает через некоторое время (например, 10 минут для киосков), что дает вам достаточно времени для платить. Если транзакция (видимая клиенту) проваливается или истекает время ожидания, распределение мест может быть возвращено обратно в пул. (Все изменения состояния обрабатываются через транзакционную базу данных, и для одной видимой для клиента транзакции может потребоваться много транзакций на уровне базы данных.)

Авиакомпании будут использовать аналогичную систему (хотя и гораздо более сложную из-за необходимости обрабатывать несколько этапов полета!) Для бронирования мест онлайн. Я полагаю, что время ожидания будет значительно больше; авиабилеты обычно бронируются заранее, чем билеты в кино, а также стоят дороже.


Имейте в виду, мой местный кинотеатр фактически не распределяет места нормально. Вместо этого они переоформили места, чтобы люди могли просто появиться с минимальной суетой. Это другая техника, но не та, которая имеет отношение к вашему вопросу!
Donal Fellows

Похоже на подбор мест для спортивных мероприятий. Вы получаете количество мест N зарезервированных на 3 минуты, пока вы решаете, хотите ли вы их на самом деле, и завершаете оплату.
AndyMcKenna

Обратите внимание, что есть два разных процесса, например, при покупке мест в авиакомпании: во-первых, вы покупаете билет без выделенного места. Во-вторых, когда вы получаете посадочный талон (или регистрируетесь онлайн), вы получаете место. Количество билетов на самом деле перепродано, потому что они знают, что в среднем определенное количество не появляется на рейс. Распределение мест, однако, похоже, работает, когда вы случайным образом назначаете вам место (первым пришел - первым обслужен), когда вы регистрируетесь, а затем позволяете вам изменить место, выбрав доступное, а затем выполнить перевод в одной транзакции. ,
Скотт Уитлок

2
@DonalFellows, не могли бы вы немного подробнее объяснить предварительную часть распределения? Вы имеете в виду резервирование некоторых мест для пользователя на некоторый период времени? Я все еще пытаюсь разобраться с проблемами, с которыми сталкиваются в этом типе системы.
Сандипан Нат

1
@SandeepanNath Не правильно в комментарии, но принцип тривиален. Место переводится в «условно распределенное» состояние, и время ожидания этого состояния отмечается одновременно. Если бронирование завершено, место становится полностью выделенным. Если нет, и время ожидания истекло, сиденье (в конце концов) перемещается обратно в основной бассейн. (Кроме того, если пользователь явно отменяет действие, сиденье перемещается обратно в бассейн. Не нужно ждать.)
Donal Fellows

4

30 секунд, которые вы видели в наши дни, часто больше похожи на 15 минут. Я не верю, что транзакция базы данных активна в течение этого периода.

Если бы я проектировал такую ​​систему, я бы так и сделал: имел бизнес-объекты Bookingи т Reservation. Д. Бронирование по существу подтверждено (т.е. оплачено) бронирования. Я хотел бы хранить их в одной таблице БД и различать по атрибуту или двум.

Выбирая свободные места, вы запрашиваете как бронирование, так и бронирование.

Когда кто-то выбирает место, вы создаете новое бронирование, таким образом показывая другим клиентам место, занятое. Второе бронирование для того же места будет отклонено - обновление БД или вставка не удастся. Если клиент подтверждает / оплачивает бронирование, вы переходите к бронированию. В периодическом пакетном задании вы удаляете все резервирования старше 15 минут (или в любое другое время, которое вы предоставляете своим клиентам).



1

Здесь задействованы как минимум 2 бизнес-процесса.

  • Процесс один:

Показать доступные места.

  • Процесс два:

Забронируйте выбранное место.

Поскольку эти процессы не следуют друг за другом неумеренно, и поскольку 2 человека могут выбрать одно и то же место, возникает проблема параллелизма.

Если ваш дизайн базы данных назначает правильное ограничение уникальности, чтобы комбинация:

-TheaterID

-SeatID

-EventID

являются уникальными, то база данных будет предотвращать дубликаты.

Следующий сценарий также возможен, но будет учтен вышеупомянутой предложенной реализацией:

Предполагая, что отображение сетки доступно для данного театра и данного события, может быть отображено:

  1. Пользователь1 отображает доступные места (и получает места 1 и 2)
  2. Пользователь2 отображает доступные места (и получает места 1 и 2)
  3. Пользователь1 немного разговаривает с клиентом по телефону
  4. Пользователь 2 идет и заказывает место 2 для своего клиента
  5. Пользователь1 пытается забронировать место 2 для своего клиента (потому что оно показывает, как доступно на его экране)
  6. Уникальный индекс не позволяет шагу 5 коммутировать данные.

Таким образом, все, что вам нужно сделать, это не более правильный дизайн базы данных и правильный выбор ограничений.

Другие более сложные подходы возможны, если вы хотите, используя очереди транзакций. В этом случае запросы сначала записываются в очередь, а затем запускают процесс каждые n секунд, но это вряд ли необходимо или практично в вашем случае.

Действительно интересная часть - что должна показать сетка списка для пользователя 1?


1

Вы можете избежать условий гонки, если откладываете распределение определенных мест.

  1. Соберите предпочтения рассадки от клиента (количество мест, цена, площадь театра, прилегающие места обязательно и т.д. ...)
  2. Сохраните запрошенные предпочтения рассадки в очереди
  3. Один за другим запросы на места забираются из очереди, места распределяются в соответствии с предпочтениями, и бронирование завершается, если места найдены.
  4. Если бронирование завершено, уведомить клиентов и почтовые билеты; в противном случае уведомите клиента, что ни один билет не соответствует предпочтениям.
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.