Стратегии кэширования и инвалидация

Главная боль кэша — не как класть данные, а как вовремя их обновлять.

Инвалидация кэша — удаление или обновление устаревших данных в кэше. Известная шутка: «в информатике две трудные задачи — инвалидация кэша и придумывание имён».

Cache-aside (lazy loading)

Самая частая стратегия. Приложение само управляет кэшом: при чтении сначала смотрит в кэш, при промахе идёт в базу и кладёт результат в кэш. При записи — пишет в базу и удаляет (инвалидирует) ключ из кэша.

ЧТЕНИЕ:
  есть в кэше? → да: вернуть
               → нет: прочитать из БД, положить в кэш, вернуть
ЗАПИСЬ:
  записать в БД, затем удалить ключ из кэша

Плюс: в кэше только то, что реально запрашивают. Минус: первый запрос после промаха медленный, и есть окно, когда кэш и база рассинхронны.

Write-through

Запись идёт через кэш: приложение пишет в кэш, а кэш синхронно пишет в базу. Кэш всегда согласован с базой. Минус — каждая запись медленнее (ждём и кэш, и базу), и кэшируется даже то, что потом не прочитают.

Write-back (write-behind)

Запись идёт в кэш, а в базу сбрасывается позже, пачкой (асинхронно). Запись очень быстрая, база разгружена. Расплата — риск потерять данные, если кэш упал до сброса. Применяют там, где скорость записи критична, а редкая потеря терпима (счётчики, метрики).

Сравнение стратегий

СтратегияСкорость записиСогласованностьРиск потери
Cache-asideобычнаяокно рассинхронанет
Write-throughмедленнеевысокаянет
Write-backочень быстраяотложеннаяесть (до сброса)

TTL и устаревание

TTL (time to live) — срок жизни записи в кэше, после которого она сама удаляется. Это страховка от вечно устаревших данных: даже если забыли инвалидировать вручную, через TTL запись протухнет и перечитается из базы. Подбор TTL — компромисс: короткий → свежее данные, но больше промахов и нагрузки на базу; длинный → меньше нагрузки, но выше риск отдать устаревшее.

Опасные эффекты

ПроблемаСуть и лечение
Cache stampedeпопулярный ключ протух — толпа запросов разом бьёт в базу. Лечат блокировкой на перечитывание и «прогревом».
Thundering herdпосле рестарта кэш пуст, вся нагрузка идёт в базу. Лечат предзагрузкой (warm-up).
Несвежие данныезабыли инвалидировать. Страхует TTL.

Итог

  • Cache-aside — гибко и популярно; write-through — согласованно, но медленнее; write-back — быстро, но рискует потерей.
  • TTL — страховка от устаревания: даже без ручной инвалидации запись протухнет сама.
  • Берегитесь cache stampede и пустого кэша после рестарта — прогревайте и блокируйте перечитывание.
Проверьте себя
1. В стратегии cache-aside что происходит при промахе чтения?
AВозвращается ошибка
BПриложение читает из базы, кладёт значение в кэш и возвращает его
CЗапрос отклоняется
DКэш полностью очищается
2. Чем write-back отличается от write-through по рискам?
AWrite-back полностью безопасен
BWrite-back быстрее, но может потерять данные, если кэш упал до сброса в базу
CWrite-through теряет данные чаще
DМежду ними нет разницы
3. Зачем кэш-записи нужен TTL?
AЧтобы ускорить запись в базу
BЧтобы запись со временем сама протухла и перечиталась — страховка от вечно устаревших данных
CЧтобы увеличить hit rate
DЧтобы отключить инвалидацию
4. Что такое cache stampede?
AПереполнение кэша по памяти
BКогда популярный ключ протух и толпа запросов одновременно бьёт в базу
CСбой сети между кэшем и базой
DСлишком высокий hit rate
Поддержать проект