Защита от двойного бронирования
Вопрос
Как не продать одно место в кинотеатре двум покупателям, которые нажали «купить» одновременно?
Попробуйте сами
Ответьте вслух за 2 минуты, как на собесе. Потом сверьтесь с тезисами: что прозвучало, а что нет.
Показать ответ и разбор
Коротко
Что должно прозвучать в ответе
Ограничение уникальности на (сеанс, место) в БД
Или условное обновление: UPDATE ... WHERE status = свободно, проверка числа затронутых строк
Временный холд места с истечением на время оплаты
Пессимистичная блокировка SELECT FOR UPDATE как вариант при низкой конкуренции
Распределённый лок в Redis только с пониманием его ограничений
Что могут спросить следом
- Что делать, если оплата не пришла за 10 минут?
- Чем опасен лок в Redis?
Разбор
Источник истины одна БД, и защиту делаю на её уровне. Самое простое: таблица билетов с уникальным ключом (сеанс, место), второй INSERT получит ошибку уникальности. Либо места заранее заведены, и бронирование это UPDATE seats SET status = 'held', hold_until = now() + interval '10 minutes' WHERE id = ... AND status = 'free': если затронуто 0 строк, место уже занято. Холд истекает, если оплата не пришла, фоновая задача или условие в запросе освобождают место. Распределённый лок в Redis добавляет точку отказа и при истечении лока во время паузы процесса не спасает, поэтому финальную проверку всё равно делает БД.
Ответьте сами, а не прочитайте
В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.