Как обновляется кэш при изменении данных на сервере
Что проверяют
Понимаете ли вы, что кэш не один: браузер, CDN, серверный кэш вроде Redis и кэш клиентской библиотеки, и у каждого своё правило обновления. Следом спрашивают, как вы проверите, что пользователь увидит новые данные, и через какое время.
Как отвечать
Сначала назовите стратегии, от них зависят проверки:
- TTL: запись живёт заданное время, потом перечитывается. Устаревшие данные в пределах TTL это не баг, а договорённость, её сверяют с требованиями;
- инвалидация при записи: схема cache-aside, сервис меняет базу и удаляет ключ, следующий запрос заполнит его заново;
- write-through: запись идёт в кэш и базу вместе, кэш свежий, но запись дороже;
- событийная инвалидация: изменение публикуется в очередь или pub/sub, и все экземпляры сервиса сбрасывают свою копию.
На уровне HTTP управляет Cache-Control: max-age задаёт срок, no-cache разрешает хранить, но требует перепроверки, no-store запрещает хранить вовсе. Перепроверка идёт по ETag и If-None-Match или по Last-Modified, и неизменный ресурс приходит ответом 304. Статику отдают с хэшем в имени файла и immutable, поэтому новая версия получает новый URL. На фронтенде TanStack Query или SWR после изменения данных инвалидируют запрос.
Инструменты: в DevTools колонка Size показывает (memory cache) или (disk cache), заголовки ответа видны в curl -I, заголовки CDN вроде Age подсказывают, откуда пришёл ответ, а redis-cli TTL key показывает, сколько ключу осталось. Сценарии: изменить данные и сразу прочитать, прочитать другим пользователем и через другой узел, поймать момент истечения TTL, запустить запись и чтение одновременно.
Где спотыкаются
Проверяют с галочкой Disable cache и говорят «всё обновляется». Реальный пользователь с кэшем увидит другое, а CDN и Redis эта галочка вообще не трогает.
Путают no-cache и no-store. Первый не запрещает кэширование, он только требует спросить сервер перед использованием.
Не проверяют гонку: запрос прочитал из базы старые данные, в этот момент запись обновила базу и удалила ключ, а первый запрос положил в кэш уже устаревшее значение. Такой баг ловится нагрузкой или точной расстановкой задержек.