Какие стратегии кэширования вы знаете и как решаете проблему инвалидации кэша?
Короткий ответ
- Cache-aside: приложение читает кэш, при промахе идёт в базу
- Write-through пишет в кэш и базу синхронно
- Write-behind копит записи и сбрасывает асинхронно
- Инвалидация: TTL, явное удаление при записи, версионирование ключей
- Cache stampede гасят блокировкой или размазыванием TTL
- Кэш — это всегда согласованность в обмен на скорость
Чаще всего используют cache-aside с TTL и явной инвалидацией при записи, отдельно защищаясь от stampede.
Как сказать вслух
пример ответаСамая распространённая схема — cache-aside: сначала смотрим в кэш, при промахе читаем из базы и кладём в кэш с TTL. Есть write-through, когда запись идёт сразу и в кэш, и в базу, и write-behind, когда записи копятся и сбрасываются асинхронно. Инвалидация — главная боль: обычно комбинируют TTL как страховку и явное удаление ключа при изменении данных. Ещё важно защищаться от ситуации, когда горячий ключ протух и тысячи запросов одновременно пошли в базу.
Подробный ответ
Основной ответ
Cache-aside (lazy loading) — приложение само управляет кэшем: читает, при промахе загружает из источника и сохраняет; минус — первый запрос медленный и возможны устаревшие данные до истечения TTL. Write-through — запись проходит через кэш в базу синхронно, кэш всегда актуален, но запись дороже. Write-behind — запись в кэш мгновенна, в базу — батчами асинхронно; быстро, но есть риск потери при падении кэша. Read-through — кэш сам умеет ходить в источник. Инвалидация: TTL (просто, но окно устаревания), явное удаление/обновление ключей при записи (точно, но нужно знать все ключи), версионирование (ключ включает версию сущности). Отдельные проблемы — cache stampede (решается mutex-замком на прогрев, вероятностным ранним обновлением, размазыванием TTL джиттером) и согласованность кэша с базой при конкурентных записях.
Ключевые моменты
- Cache-aside — дефолт. Прост, переживает падение кэша (деградация, а не отказ), поэтому выбирается в большинстве сервисов с Redis.
- Stampede. Протухший горячий ключ отправляет лавину запросов в базу. Лечится локом на перезагрузку значения и джиттером TTL.
- Удалять, а не обновлять. При записи в базу безопаснее удалить ключ, чем записать новое значение: обновление из двух конкурентных потоков может оставить в кэше устаревшие данные.
- Уровни кэширования. Кэш бывает в памяти процесса, в Redis/Memcached, на CDN и в HTTP-заголовках — у каждого уровня своя инвалидация.
Практический контекст
В реальных сервисах кэшируют тяжёлые выборки, профили, конфигурацию, результаты внешних API. Интервьюер обычно копает в инвалидацию и stampede: «данные обновились — что с кэшем?», «ключ протух под нагрузкой — что произойдёт?». Сильный ответ включает честное признание, что кэш добавляет рассинхронизацию, и выбор TTL исходя из допустимой устаревшности данных для бизнеса.
Частые ошибки
- Называют только «положим в Redis», не зная ни одной стратегии записи
- Игнорируют stampede и прогрев кэша под нагрузкой
- Предлагают обновлять значение в кэше при записи, создавая гонку вместо простого удаления ключа