Система умной парковки ломается не на карте и не на поиске, а в тот момент, когда несколько водителей одновременно пытаются занять одно физическое место.
Глава собирает в одну архитектуру временную бронь, счётчик свободных мест, контроль въезда по номеру машины и автоматическое освобождение просроченной брони.
В интервью и инженерных обсуждениях этот кейс полезен тем, что быстро показывает, умеете ли вы защищать инварианты редкого ресурса под высокой конкуренцией.
Временная бронь
Критичный продуктовый шаг здесь не продажа места навсегда, а короткая бронь, которую нужно оформить быстро и снять без ручного участия, если водитель не приехал.
Счётчик мест
Самый важный инвариант живёт в одном числе: свободных мест не может стать меньше нуля, даже если в одну парковку одновременно стучатся десятки клиентов.
Контур тайм-аута
Просроченные брони лучше убирать отдельным фоновым контуром, чтобы не усложнять синхронный API и не держать место заблокированным слишком долго.
Контроль въезда
Проверка номера машины и команда шлагбауму живут в другом операционном мире, поэтому этот путь стоит отделять от логики бронирования уже на ранней архитектуре.
Публичное интервью на C++ Russia 2023 предлагает спроектировать систему умной парковки: пользователь заранее резервирует место, въезжает по номеру машины, а система должна выдерживать конкуренцию и защищаться от .
Источник
Оригинальный разбор
Разбор основан на публикации в Telegram-канале «Книжный куб» и записи публичного интервью.
Видеозапись интервью
Полная запись публичного интервью длится около 30 минут и доступна на YouTube.
Смотреть на YouTubeПостановка задачи
Система умной парковки
Это сеть платных парковок со шлагбаумами и мобильным приложением. Пользователь заранее резервирует место, получает ограниченное по времени подтверждение и затем заезжает без ручной проверки по номеру автомобиля.
Функциональные требования
Поиск парковки
Поиск по геолокации с показом доступных парковок и числа свободных мест.
Создание брони
Атомарное резервирование одного свободного места без перепродажи того же слота.
Отмена по тайм-ауту
Автоматическое снятие брони, если водитель не приехал вовремя.
Въезд и выезд
Автоматическое распознавание номера и открытие шлагбаума для валидной брони.
Нефункциональные требования
Высокая конкуренция
Пиковые нагрузки приходятся на часы начала и конца рабочего дня, а также на популярные торговые точки. Несколько водителей могут одновременно претендовать на одно и то же место.
Без двойного бронирования
Ошибка в этой системе очень заметна пользователю: нельзя отдать одно физическое место двум машинам одновременно.
На уровне модели это не мгновенная покупка, а с ограниченным сроком жизни. Поэтому критический путь должен удерживать строгую между счётчиком мест и записью о брони.
Связанная глава
Геопоиск и горячие зоны
Полезна для разговора о локальных пиках нагрузки и географическом разбиении парковок.
Высокоуровневая архитектура
Система умной парковки: архитектурная карта
временная бронь, контроль въезда и снятие просроченной брониКонтур бронирования
Контур доступа и фоновой обработки
Сквозной сценарий умной парковки: бронирование места, проверка въезда и автоматическое освобождение просроченной брони.
Архитектура сознательно разделяет три контура: оформление брони, физический контроль въезда и фоновое снятие просроченных броней. Так API, контур ANPR/LPR и фоновые воркеры можно масштабировать независимо и деградировать по-разному.
Основные сущности
Parking
{
id: UUID,
gps_coordinates: {lat, lon},
total_capacity: int,
free_spots_counter: int, // семафор!
address: string
}Booking
{
id: UUID,
user_id: UUID,
parking_id: UUID,
car_plate: string,
created_at: timestamp,
expires_at: timestamp,
status: enum (pending, confirmed, cancelled, expired)
}Счётчик свободных мест
Центральная техническая сложность здесь — атомарно уменьшить счётчик свободных мест так, чтобы он никогда не уходил ниже нуля. Именно на этой операции и появляется гонка между параллельными запросами на одно и то же место.
Redis: Lua-скрипт
Рекомендуется-- parking_book.lua
local counter = redis.call('GET', KEYS[1])
if tonumber(counter) > 0 then
return redis.call('DECR', KEYS[1])
else
return -1 -- Нет свободных мест
endПлюсы
Атомарность на одном ключе, простая логика и высокая скорость.
Минусы
Нужно отдельно продумать отказоустойчивость и синхронизацию с основной БД.
PostgreSQL: условный UPDATE
UPDATE parkings SET free_spots = free_spots - 1 WHERE id = $1 AND free_spots > 0; -- affected_rows = 0 → мест нет
Плюсы
Строгие транзакционные гарантии и единый источник истины для состояния.
Минусы
Под высокой конкуренцией быстро упирается в блокировки строк и нагрузку на БД.
Рекомендуемый подход
Redis хорошо подходит для быстрого удержания слота на короткое время, а PostgreSQL — для финальной записи и истории. На практике это превращается в двухступенчатую схему: быстрый семафор спереди и надёжное хранилище состояния сзади.
Автоматическое освобождение по тайм-ауту
Если водитель не приехал за 15 минут, место нельзя держать бесконечно. Для этого у брони должен быть явный и отдельная , которая инициирует отмену неявки.
AWS SQS: задержанная доставка
# При бронировании
sqs.send_message(
QueueUrl=timeout_queue,
MessageBody={"booking_id": "...", "parking_id": "..."},
DelaySeconds=900 # 15 минут
)
# Через 15 минут воркер проверяет:
# - Если машина не приехала → INCR счётчик, отменить бронь
# - Если приехала → ничего не делатьАльтернатива — RabbitMQ Delayed Message Plugin, если очередь нужно держать внутри собственного контура.
Воркер отмены и сервис въезда должны быть : повторное сообщение не должно вернуть место в пул дважды и не должно повторно отменить уже завершённую бронь.
Географическое разбиение
Для этой системы естественно использовать по регионам, а ещё точнее — . Большинство запросов локальны: водитель ищет парковку рядом, а не по всей стране.
Стратегия
- Ключ разбиения можно строить из региона или geohash-ячейки парковки.
- Запросы «покажи ближайшие парковки» обычно обслуживаются внутри одного региона.
- Пересечение между регионами остаётся редким исключением, а не нормальным режимом.
Важно: популярные районы быстро превращаются в . Центр города, аэропорт или крупный торговый центр лучше заранее дробить на подзоны и разгружать чтение кэшем или репликами.
Ключевые выводы
Семафор на счётчике мест
Критичный инвариант живёт в одном месте: место либо занято, либо свободно. Любая гонка вокруг декремента ломает весь сценарий.
История бронирований обязательна
Отдельная сущность брони нужна не только продукту, но и аудиту, поддержке, аналитике и восстановлению состояния после сбоев.
Тайм-аут — отдельный контур
Лучше вынести просрочку брони из синхронного API в фоновый контур с очередью и явно заданным сроком жизни брони.
География помогает с масштабированием
Парковки естественно разбиваются по регионам, поэтому локальность трафика можно использовать уже на ранней архитектуре.
Что важно проговорить на интервью
Здесь ценят не только рабочую схему, но и умение явно назвать между скоростью принятия брони, строгостью инвариантов и ценой более сложной операционной схемы.
Оценка интервьюера
✓ Сильные стороны
- Быстрое выделение главного инварианта: нельзя отдать одно место двум водителям.
- Правильное внимание к тайм-ауту, отказам и полному жизненному циклу брони.
- Понимание, что география влияет на масштабирование и распределение нагрузки.
- Хорошая общая структура ответа для короткого публичного интервью.
⚠ Области для улучшения
- Отдельную сущность брони нужно было назвать и обсудить раньше.
- Не хватает численной оценки нагрузки и явного sizing по пикам.
- Выбор между Redis и PostgreSQL стоит доводить до более явного решения.
- Не до конца раскрыт операционный контур вокруг ANPR/LPR и обработки сбоев на въезде.
Связанные главы
- Hacking the System Design Interview (краткий обзор) - даёт хороший интервью-фрейминг для задач, где нужно удержать корректное состояние ресурса под высокой конкуренцией.
- Примеры задач по системному дизайну - ставит кейс умной парковки рядом с другими продуктовыми задачами и помогает сравнить архитектурные решения между доменами.
- Лэсли Лэмпорт: причинность, Paxos и инженерное мышление - усиливает теорию о порядке событий, консистентности и корректности распределённых протоколов.
- Краткосрочная подготовка к интервью по системному дизайну - помогает упаковать решение в интервью-формат: требования, инварианты, риски и план эволюции.
