Как строится логика синхронизации корзин и где она реализована
Что проверяют
Понимаете ли вы, что корзина магазина живёт сразу в нескольких местах: в браузере, в мобильном приложении, на сервере, и синхронизировать нужно именно их, а не потоки внутри одной JVM. Следом спрашивают, что происходит с гостевой корзиной после входа и как решается конфликт одновременных правок.
Как отвечать
Начните с источника истины: серверный сервис корзины, клиент держит только кеш. Дальше каркас:
- хранилище: корзина пользователя лежит в базе или в Redis с TTL, гостевая привязана к анонимному идентификатору в cookie;
- слияние при логине: гостевая корзина вливается в пользовательскую по явному правилу, например сумма количеств или приоритет последней правки, после чего удаляется;
- конкурентные правки: два устройства меняют одну корзину. В JPA это оптимистичная блокировка через поле с
@Version, Spring при конфликте бросаетOptimisticLockingFailureException, операцию повторяют. В Redis аналог этоWATCH/MULTIили Lua-скрипт; - идемпотентность: повтор запроса после таймаута не должен удвоить позицию, поэтому клиент шлёт ключ идемпотентности или операция звучит как «установить количество», а не «прибавить»;
- доставка изменений: второе устройство узнаёт о них при следующем запросе или через WebSocket, если нужна мгновенность;
- актуализация: цены и остатки пересчитываются при оформлении, корзина их только кеширует.
На вторую часть вопроса отвечайте про свой проект: какой сервис владеет корзиной, какая таблица или ключ, какой эндпоинт делает слияние.
Где спотыкаются
Отвечают про synchronized и ReentrantLock. Такая блокировка работает внутри одного процесса, а сервис корзины обычно запущен в нескольких экземплярах за балансировщиком.
Забывают про гостевую корзину. Вопрос «что будет с товарами после входа» ставит в тупик, хотя это самый частый сценарий.
Доверяют цене из корзины при оплате. Цена и остаток могли измениться, и без пересчёта заказ уйдёт по старой цене.