Кеш — это не магия: разбираемся на пальцах

10.02.2026 · 6 мин

Крупный план микросхем памяти

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

Зачем вообще нужен кеш

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

Если данные меняются на каждый запрос или их вычисление и так дешёвое — кеш не ускорит систему, а добавит сложности без пользы.

Самая частая проблема: инвалидация

Есть известная шутка про то, что в программировании есть только две сложные вещи: именование переменных и инвалидация кеша. Она не преувеличивает. Данные в кеше устаревают, и вопрос «когда их обновить» решается тремя основными способами.

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

Инвалидация по событию — кеш сбрасывается явно в момент, когда данные изменились. Точнее, но требует не забыть сбросить кеш во всех местах, где данные могут поменяться, — а это источник трудноуловимых багов, когда забыли один из путей изменения.

Write-through — запись одновременно идёт и в основное хранилище, и в кеш, так что рассинхронизации не возникает вовсе, но это усложняет логику записи.

Кеш-промах под нагрузкой

Отдельная ловушка — так называемый thundering herd: когда популярный ключ кеша истекает, и сразу множество запросов одновременно бросаются пересчитывать значение и бьют по источнику данных всей силой сразу. Я один раз словил это на проде: кеш главной страницы сбрасывался раз в минуту, и в момент сброса база данных получала кратковременный, но очень заметный всплеск нагрузки.

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

Когда кеш создаёт больше проблем, чем решает

Если после внедрения кеша в системе появляются баги вида «я обновил данные, а старые значения всё ещё показываются» чаще, чем раз в квартал — вероятно, стратегия инвалидации выбрана неправильно для этого конкретного случая использования. Иногда правильный ответ — не более хитрый кеш, а более простой и быстрый путь к исходным данным: индекс в базе, денормализация, материализованное представление.

Кеш — инструмент, а не обязательный этап взросления системы. Добавлять его стоит, когда измерения показали конкретную проблему производительности, а не «на всякий случай».