Парковка со шлагбаумом: что проектируем, а что нет
Из нефункциональных требований кандидат зацепился за два: парковки в разных городах России и высокая доступность — значит, система заведомо распределённая и одним дата-центром не обойтись. Конкретные значения нагрузки решили не обсуждать, ограничившись тем, что она будет расти вместе с бизнесом. За скобки вынесли бэк-офис, где заводят новые парковки и оформляют документы, и обработку платежей — ею занимается кто-то внешний.
Внешней системой признали и контроль доступа: шлагбаум с камерой, которая читает госномер. Проектировать её не стали, договорились принимать от неё два события — машина заехала и машина выехала. Саму парковку тоже упростили: план мест не рисуем, конкретное место не выдаём, для каждой парковки хранится только счётчик свободных мест. Кандидат, много лет проработавший в авиации, по привычке называл их сидячими местами, как в самолёте. Овербукинг решили сознательно не поддерживать.
Семафор свободных мест и отложенные события
Интервьюер добавил сценарий, до которого кандидат не дошёл: смотреть надо не на одну парковку, а на прямоугольник карты — торговый центр и всё вокруг него. Отсюда взялся гео-индекс по координатам и понимание, что запрос одновременно нагруженный и постоянно меняющийся: пользователь двигает карту и обновляет экран. Координаты парковок кэшировать можно, они меняются редко, а счётчики свободных мест — опасно, и на запись их кэшировать нельзя ни в коем случае.
Ядром решения стал атомарный декремент счётчика с запретом уходить ниже нуля — по сути семафор. Не выбрать значение и записать на единицу меньше, а операция, которая при нуле возвращает отказ, и в приложение прилетает «пока вы думали, места разобрали». Отмену брони и выезд машины обрабатывают обратным инкрементом. Для брони, не подтверждённой приездом за пятнадцать минут, кандидат завёл очередь отложенных сообщений и вторую очередь — на уведомления. Разделение по координатам синхронизации счётчиков между регионами не требует.
Разбор: что удалось и что интервьюер сделал бы иначе
Разбор начали с сильных сторон: границы очерчены аккуратно, а кандидаты часто закапывают себя, соглашаясь спроектировать всё сразу. Замечание касалось пропущенной сущности — самих заказов. Кандидат согласился и добавил историю бронирований: поток событий пользователя со статусами, практически только на запись, лог-ориентированное хранилище, подключённое к общей шине. Он сам заметил иронию: занимается data science и обычно упрекает других, что данных не собрали, а тут забыл про них.
Своё решение интервьюер построил иначе: PostgreSQL с ограничением на неотрицательный счётчик и явная статусная модель заказа — создан, оплачен, пользователь приехал, пошёл отсчёт времени. Нагрузку на чтение карты он снимал отдельной копией данных, соглашаясь на лаг: человек видит последнее место, а при бронировании получает отказ. Гео-распределение, по его мнению, проще сделать на балансировке трафика по регионам — никто не бронирует место во Владивостоке и Москве одновременно. Отдельно прозвучало, что интервью шло тридцать минут вместо обычного часа.
Что стоит унести с собой
- 01Счётчик мест — это не число в базе, а семафор: без атомарной операции, которая отказывает на нуле, овербукинг приходит через обычную гонку запросов.
- 02Конкуренция за места обостряется не всегда: пока на парковке много мест, борьбы нет — жарко становится на последних местах и в утренние и вечерние пики.
- 03Хранилище истории заказов стоит заводить сразу, иначе статусы и аналитику придётся восстанавливать из промежуточных таблиц, которые система по ходу удаляет.
- 04Схему оценивают и по читаемости: критерий в том, понятно ли по ней, что происходит, когда автор перестаёт её комментировать.
Источники
- Автоматические субтитры записи
- Запись интервью