System Design Space
Граф знанийНастройки

Обновлено: 25 марта 2026 г. в 04:52

Система бронирования отелей

medium

Публичное интервью на ArchDays 2022: overbooking, inventory-модель, конкурентность и масштабирование.

Бронирование отелей сложно не только поиском, а календарной моделью доступности: номера продаются на интервалы дат, синхронизируются с поставщиками и легко уходят в race conditions.

Глава помогает связать inventory по диапазонам дат, availability search, reservation workflow, supplier sync и compensation logic после partial failure.

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

Business Correctness

Требуется корректное состояние заказа при конкурирующих запросах и ретраях.

User Experience

Надо защищать critical user flow при скачках трафика и частичных деградациях.

Transactional Boundaries

Явно задавайте, где нужна сильная консистентность, а где допустима eventual.

Evolution Path

Покажите, как архитектура растёт от MVP до multi-region масштаба.

На конференции ArchDays 2022 мы провели публичное System Design интервью в формате, максимально приближённом к реальному собеседованию в Big Tech компаниях. Задача — спроектировать систему бронирования отелей. Этот разбор покажет весь процесс от формализации требований до обсуждения масштабирования.

Связанный кейс

Проектирование Airbnb

Похожая задача с geo-search, dynamic pricing и двусторонним маркетплейсом.

Читать обзор

Видеозапись интервью

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

Смотреть на YouTube

Постановка задачи

Hotel Booking System

Спроектировать систему бронирования отелей для российского рынка.

20 000 отелей

Общее количество отелей в системе

1 000 000 номеров

Суммарное количество номеров

Функциональные требования

Просмотр информации

Детальная информация об отелях и номерах

Онлайн бронирование

Выбор дат и типа номера с оплатой

Оплата

Интеграция с платёжной системой

Отмена брони

Возможность отменить бронирование

Важное бизнес-требование: Overbooking до 10%

Система должна поддерживать овербукинг — возможность продать больше номеров, чем есть в наличии. Это стандартная практика в гостиничном бизнесе, так как часть броней отменяется или гости не приезжают (no-show).

Что вынесли за scope

Авторизация/аутентификацияАдмин-панельПоиск отелейОтзывы и рейтинги

Оценка нагрузки (Back of the Envelope)

Средняя длина брони5 ночей
Средняя заполняемость70%
Номеров занято ежедневно700 000
Новых бронирований в день~200 000
Средняя нагрузка~2.3 TPS

Важно: Средняя нагрузка невелика, но будут значительные пики — сезонные распродажи, праздники, flash-sales. Система должна выдерживать нагрузку в 10-100 раз выше средней.

Public API

GET/v1/hotels/{hotel_id}

Получение информации об отеле

GET/v1/hotels/{hotel_id}/rooms/{room_type_id}

Получение информации о типе номера

POST/v1/reservations

Создание бронирования

{
  "hotel_id": "123",
  "room_type_id": "456",
  "start_date": "2024-03-15",
  "end_date": "2024-03-20",
  "guest_info": { ... }
}
DELETE/v1/reservations/{reservation_id}

Отмена бронирования

Эволюция модели данных

Одна из ключевых тем интервью — как правильно спроектировать модель данных для поддержки overbooking и высокой конкурентности.

Наивный подход: Таблица Reservations

Reservation
├── id
├── hotel_id
├── room_type_id
├── room_id (конкретный номер)
├── start_date
├── end_date
├── status
└── guest_id

Проблема 1: Для проверки доступности нужно делать COUNT по всем броням на дату

Проблема 2: Сложно реализовать overbooking — нужно знать точное количество доступных номеров

Проблема 3: Race condition при одновременном бронировании

Улучшенный подход: Inventory-based модель

RoomTypeInventory
├── hotel_id
├── room_type_id
├── date
├── total_rooms (всего номеров этого типа)
├── total_reserved (забронировано)
└── overbooking_limit (лимит овербукинга)

Constraint: total_reserved <= total_rooms * (1 + overbooking_limit)

Преимущество 1: Мгновенная проверка доступности — один SELECT

Преимущество 2: Overbooking встроен в модель через overbooking_limit

Преимущество 3: Атомарное обновление через UPDATE с условием

Обработка конкурентности

Критически важная тема — как избежать race condition, когда два пользователя пытаются забронировать последний номер одновременно.

Pessimistic Locking (SELECT FOR UPDATE)

BEGIN;
SELECT * FROM room_inventory 
WHERE hotel_id = ? AND room_type_id = ? AND date = ?
FOR UPDATE;

-- Проверка и обновление
UPDATE room_inventory SET total_reserved = total_reserved + 1 ...

COMMIT;

Плюсы

Гарантированная консистентность, простая логика

Минусы

Блокировка строки, снижение throughput, deadlock риск

Optimistic Locking (Repeatable Read)

-- Isolation Level: REPEATABLE READ
BEGIN;

UPDATE room_inventory 
SET total_reserved = total_reserved + 1
WHERE hotel_id = ? 
  AND room_type_id = ? 
  AND date = ?
  AND total_reserved < total_rooms * (1 + overbooking_limit);

-- Если affected_rows = 0, номеров нет
COMMIT;

Плюсы

Высокий throughput, нет блокировок, атомарность

Минусы

Нужен retry при конфликтах

Database Constraints

ALTER TABLE room_inventory 
ADD CONSTRAINT check_overbooking 
CHECK (total_reserved <= total_rooms * (1 + overbooking_limit));

Дополнительная защита на уровне БД — даже при багах в коде система не нарушит лимиты.

Выбор для нашего масштаба

При нагрузке ~2.3 TPS с пиками до 100 TPS Optimistic Locking — оптимальный выбор. Он обеспечивает высокую производительность без сложности распределённых блокировок. Pessimistic Locking имеет смысл при очень высокой конкуренции за конкретные ресурсы.

Стратегии масштабирования

Партиционирование по времени

Разделение таблицы inventory по месяцам или кварталам.

  • Старые данные можно архивировать
  • Запросы работают с меньшим объёмом данных
  • Упрощает maintenance операции

Шардирование по hotel_id

Распределение данных по разным шардам на основе ID отеля.

  • Горизонтальное масштабирование записи
  • Изоляция нагрузки между отелями
  • Consistent hashing для распределения

Ключевые выводы из интервью

1

Начинайте с уточняющих вопросов

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

2

Итеративно улучшайте дизайн

Показали эволюцию от наивной модели Reservation к Inventory-based подходу. Интервьюер оценивает не финальный ответ, а ход мыслей.

3

Обосновывайте выбор стратегии конкурентности

Pessimistic vs Optimistic locking — классический trade-off. Важно объяснить, почему выбрали конкретный подход для данной нагрузки.

4

Думайте о масштабировании заранее

Даже если текущая нагрузка невелика, покажите понимание того, как система будет расти и какие стратегии применить.

Связанные главы

  • Airbnb - показывает смежный marketplace-кейс с availability-моделью, pricing и высокой конкуренцией за инвентарь.
  • Payment System — платёжная система - дополняет тему транзакционной корректностью, идемпотентностью и обработкой финансовых side effects.
  • Hacking the System Design Interview (short summary) - усиливает интервью-фрейминг и помогает структурировать аргументацию по trade-offs в booking-системах.
  • Примеры задач по системному дизайну - ставит кейс бронирования отелей в общий контекст и облегчает сравнение архитектур с другими доменами.

Чтобы отмечать прохождение, включи трекинг в Настройки