Як система бронювання сидінь у кінотеатрі заважає багатьом користувачам резервувати однакові місця?


34

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

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


10
"це так просто, як перший, який натискає КУПИТИ, отримує місця, а другий отримає повідомлення про помилку". Це.
янніс

2
Так, напевно, у зайнятий день із десятком машин здається, що це буде біль, хоча.
mbwasi

2
Можливо, але майте на увазі, що користувачі проводять більшу частину свого часу на інших екранах (вводячи платіжні реквізити, чекаючи надрукування квитків тощо), тому вони не будуть обирати місця одночасно, і не у всіх однакові переваги сидінь, тому навіть ті, хто збирається одночасно, швидше за все, виберуть різні місця. Я б не очікував, що буде стільки зіткнень.
Дейв Шерохман

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

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

Відповіді:


27

Класичний метод зробити це - використовувати транзакційну базу даних (щоб не було сутичок) і здійснити попереднє розподіл місця, яке закінчується через деякий проміжок часу (наприклад, 10 хвилин для кіосків), що дає вам достатньо часу для платити. Якщо транзакція (видима для клієнта) випадає або вичерпується, розподіл місць може бути повернуто назад у пул. (Усі зміни стану обробляються через транзакційну базу даних, і одна видима для клієнта транзакція може зажадати багатьох транзакцій на рівні бази даних.)

Авіакомпанії використовуватимуть аналогічну систему (хоча і набагато складнішу через необхідність обробляти кілька льотних ніг!) Для бронювання місць в Інтернеті. Я б міг уявити, що час очікування буде значно довшим; Квитки зазвичай забронюються далі, ніж квитки в кіно, і вони дорожчі.


Зауважте, мій місцевий кінотеатр насправді не розподіляє місця нормально. Натомість вони занадто забезпечили місця, щоб люди могли просто приїхати з мінімальною суєтою. Це інша техніка, але не одна, що стосується вашого питання!
Дональні стипендіати

Подібно до вибору місць для спортивних змагань. Ви отримуєте N кількість місць, зарезервовану на 3 хвилини, поки ви вирішите, чи дійсно їх хочете, і завершите оплату.
AndyMcKenna

Зауважте, що, наприклад, купуючи крісла авіакомпанії, є два різні процеси: по-перше, ви купуєте квиток без виділеного місця. По-друге, коли ви отримаєте свій посадковий талон (або якщо ви зареєструвались в Інтернеті), то отримаєте місце. Кількість квитків насправді перепродана, оскільки вони знають, що в середньому певна кількість не відображається за рейсом. Однак, здається, розподілення сидінь працює, випадковим чином призначаючи вам місце (перший прийшов-перший-сервіс) під час реєстрації, а потім дозволяє змінити місце, вибравши доступне, а потім здійснивши передачу однією транзакцією .
Скотт Вітлок

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

1
@SandeepanNath Не належним чином у коментарі, але принцип тривіальний. Сидіння переводиться в «попередньо розподілений» стан, і час відстеження цього стану відзначається одночасно. Якщо бронювання завершено, місце стає повністю відведеним. Якщо ні, і час очікування досягнуто, сидіння (зрештою) переміщується назад в основний басейн. (Крім того, якщо користувач явно скасує, тоді місце перенести прямо назад у басейн. Не потрібно чекати.)
Дональд

4

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

Якби я проектував таку систему, я б це робив: майте бізнес-об’єкти Booking та Reservation. Бронювання - це фактично підтверджені (тобто оплачені) бронювання. Я б зберігав їх у одній таблиці БД і розрізняв за атрибутом чи двома.

Обираючи доступні місця, ви запитуєте як бронювання, так і бронювання.

Коли хтось обирає місце, ви створюєте нове бронювання, тим самим показуючи іншим клієнтам місце як прийняте. Друге бронювання на те саме місце буде відхилено - оновлення або вставлення БД не вдасться. Якщо замовник підтвердить / оплатить бронювання, ви перейдете на бронювання. У періодичному пакетному завданні ви видаляєте всі бронювання старше 15 хвилин (або в будь-який час, який ви надаєте своїм клієнтам).



1

Тут беруть участь щонайменше 2 бізнес-процеси.

  • Перший процес:

Показати наявні місця.

  • Процес другий:

Забронюйте вибране місце.

Оскільки ці процеси не слідують один одному нескромно, і оскільки 2 людини можуть обрати одне місце, виникає проблема одночасності.

Якщо дизайн вашої бази даних призначає правильне обмеження унікальності, так що комбінація:

-ТеатрID

-SeatID

-EventID

є унікальними, тоді база даних запобіжить дублювання.

Наступний сценарій також можливий, але буде вирішено вищезапропонованою реалізацією:

Припускаючи вигляд сітки, доступного для певного театру та даної події, може бути відображено:

  1. User1 відображає доступні місця (і отримує місця 1 і 2)
  2. User2 відображає доступні місця (і отримує місця 1 і 2)
  3. User1 трохи спілкується з клієнтом по телефону
  4. User2 йде та бронює місце 2 для свого замовника
  5. Користувач1 намагається забронювати місце для свого замовника 2 (оскільки це відображається як наявне на його екрані)
  6. Унікальний індекс перешкоджає кроку 5 коммутувати дані.

Отже, все, що вам потрібно зробити, може бути не більш правильним дизайном бази даних та правильним вибором обмежень.

Інші більш складні підходи можливі, якщо ви хочете, використовуючи черги транзакцій. У цьому випадку запити записуються спочатку до черги, а потім запускається процес кожні n секунд, але це навряд чи є необхідним або практичним у вашому випадку.

Дійсно цікава частина - що має показувати сітка списку для користувача 1?


1

Ви можете уникнути умови гонки, якщо відкладете виділення конкретних місць.

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