Кеширование в веб-проекте: сравнение подходов
In-process-кеш, Redis, HTTP-кеш и CDN решают одну задачу, но платят за неё по-разному. Сравниваем задержку, согласованность, отказоустойчивость и стоимость каждого подхода на примере веб-приложения.

Кеширование ускоряет веб-приложение только до тех пор, пока вы понимаете, где лежат данные, кто их видит и когда они устаревают. Локальный кеш даёт минимальную задержку, Redis переживает несколько экземпляров приложения, HTTP-кеш снимает запросы с сервера, а CDN переносит часть трафика ближе к пользователю. Ниже — сравнение этих подходов для веб-проекта на Django 5.x или другом серверном фреймворке, с Redis 7.x и обычной HTTP-инфраструктурой.
Что именно сравниваем
Кеш — это копия результата, которую можно получить дешевле, чем выполнить исходную операцию заново. В веб-проекте такой результат может быть разным: ответ API, HTML-страница, запись из базы, результат тяжёлого расчёта или файл изображения.
Подходы отличаются не только скоростью чтения. Важнее четыре свойства:
- область видимости — один процесс, все экземпляры приложения или весь интернет;
- согласованность — насколько свежие данные увидит пользователь;
- поведение при сбое — продолжит ли работать приложение без кеша;
- цена — память, сетевые обращения, инфраструктура и сложность очистки.
Кеш не исправляет медленную архитектуру. Он временно прячет стоимость операции, а затем предъявляет счёт в виде устаревших данных, промахов по кешу или проблем с очисткой.
Четыре уровня кеширования
| Подход | Где лежит копия | Что ускоряет | Главная цена |
|---|---|---|---|
| In-process | Память процесса приложения | Повторные вычисления и чтение небольших объектов | Разные экземпляры видят разные данные, память ограничена |
| Redis | Отдельный сервис в сети | Общие данные, сессии, результаты запросов и фоновых задач | Сетевой вызов, обслуживание и отдельная точка отказа |
| HTTP-кеш | Браузер или промежуточный прокси | Повторное получение ответов клиентом | Сложно отзывать уже выданные ответы |
| CDN | Пограничные узлы сети доставки | Статику и публичные ответы рядом с пользователем | Настройка правил, очистка объектов и стоимость трафика |
Термин: cache hit — попадание в кеш, когда нужный объект найден и исходную операцию выполнять не пришлось. Cache miss — промах: приложение обращается к базе, внешнему API или вычислителю и затем может сохранить результат.
In-process-кеш: самый быстрый, но локальный
Такой кеш хранится в памяти конкретного процесса. Он подходит для данных, которые можно безопасно пересоздать: разобранной конфигурации, списка редко меняющихся справочников, результата дорогой функции с коротким сроком жизни.
Преимущество очевидно: нет сетевого обращения. Но веб-приложение обычно запускают в нескольких процессах или контейнерах. Запрос, попавший на первый экземпляр, заполнит его память, а следующий запрос может уйти на второй экземпляр, где кеш пуст. После перезапуска процесса все записи исчезнут.
Это хороший первый слой для небольшого объекта, который не обязан быть одинаковым на всех узлах. Например, можно кешировать результат разбора шаблона или локальный справочник, если изменение данных допускает задержку до перезапуска либо короткого TTL.
Цена подхода
- Кеш занимает память приложения и конкурирует с рабочими объектами.
- При нескольких воркерах растёт суммарное потребление памяти.
- Инвалидация между процессами не происходит автоматически.
- После деплоя возможен массовый прогрев: все процессы одновременно обратятся к базе.
Выбирайте in-process-кеш, когда объект маленький, его допустимо потерять, а рассинхрон между экземплярами не меняет бизнес-результат. Для остатков товара, прав доступа и баланса это обычно слишком слабая гарантия.
Redis: общий кеш для нескольких экземпляров
Redis 7.x хранит данные в отдельном сервисе и становится общей точкой для приложений, фоновых воркеров и иногда нескольких сервисов. Это решает главную проблему локального кеша: любой экземпляр получает одну и ту же запись по ключу.
Цена — сетевой переход и новая инфраструктура. Даже быстрый Redis не отменяет задержку сети, сериализацию объекта и ожидание соединения. Если приложение запрашивает из кеша десятки мелких значений по одному, преимущество может исчезнуть. Крупные объекты тоже опасны: они увеличивают сетевой трафик и давление на память Redis.
Где Redis оправдан
- результат дорогого SQL-запроса, которым пользуются несколько экземпляров приложения;
- данные, которые должны быть доступны веб-процессам и фоновой обработке;
- ограничители частоты запросов и временные блокировки;
- короткоживущие результаты внешнего API, чтобы не повторять дорогой вызов.
Ключ должен включать все параметры, влияющие на результат: например, идентификатор пользователя, язык, регион и версию схемы ответа. Иначе кеш начнёт возвращать корректный результат, но не тому пользователю или не для той локали.
TTL сам по себе не решает проблему свежести. Если запись в базе изменилась, старая копия останется доступной до окончания TTL. Для критичных данных нужна явная очистка или версия ключа. Схемы с устареванием и фоновой перегенерацией позволяют не заставлять первый пользовательский запрос ждать, но требуют защиты от одновременного пересоздания одного объекта.
HTTP-кеш: запрос не доходит до приложения
HTTP-кеш работает на стороне браузера и промежуточных кешей. Сервер сообщает, можно ли сохранять ответ и как долго. При повторном обращении клиент может использовать локальную копию или проверить её условным запросом, не скачивая тело ответа заново.
Сильная сторона подхода — запрос может не дойти ни до приложения, ни до базы. Слабая — вы не контролируете все копии после отправки ответа. Если публичная страница получила срок хранения в час, исправление может не появиться у части пользователей до окончания этого срока.
Для версионируемых статических файлов безопаснее использовать имя или URL с версией: при изменении файла меняется адрес, а старую копию можно оставить жить до естественного истечения срока. Для персональных ответов нужно особенно внимательно определить, кому разрешено хранение и может ли ответ использоваться другим пользователем.
Что проверить в заголовках
- можно ли хранить ответ в браузере и промежуточном кеше;
- учитываются ли язык, кодировка, регион и другие параметры, меняющие тело ответа;
- не попадает ли персональная информация в общий кеш;
- совпадает ли срок хранения с допустимой задержкой обновления данных;
- есть ли стратегия для отзыва ошибочного или устаревшего ответа.
HTTP-кеш особенно выгоден для публичных GET-ответов, изображений, CSS, JavaScript и страниц, которые одинаковы для большого числа пользователей. Он не заменяет кеширование результата внутри приложения: это другой слой с другой областью действия.
CDN: кеширование ближе к пользователю
CDN хранит копии объектов на пограничных узлах и отдаёт их из точки, которая может находиться ближе к клиенту, чем ваш сервер. Для изображений, видео, архивов и статических файлов это обычно самый заметный способ уменьшить задержку и исходящий трафик.
CDN начинает приносить пользу, когда объект публичный, достаточно крупный или его запрашивают пользователи из разных регионов. Для персональной страницы пользователя CDN требует осторожной настройки: ошибка в правилах может превратить приватный ответ в общий.
Главная операционная проблема — очистка. Удалить файл на origin-сервере недостаточно: копия на узле CDN может продолжать отдаваться. Поэтому важные объекты получают версионируемые адреса, а принудительная очистка используется для аварийных случаев, а не как обычный механизм публикации.
Как выбрать подход
Сначала определите не технологию, а допустимую ошибку. Если пользователь может увидеть данные пятиминутной давности, Redis или HTTP-кеш с таким TTL может быть приемлем. Если старый ответ создаёт финансовый или доступный по правам риск, автоматическое кеширование нужно ограничить или дополнить явной инвалидацией.
| Ситуация | Первый кандидат | Почему | Что контролировать |
|---|---|---|---|
| Один процесс, маленький неизменяемый объект | In-process | Минимальная задержка и простая настройка | Потребление памяти и очистку после релиза |
| Несколько экземпляров приложения | Redis | Единое хранилище для всех процессов | Доступность Redis, размер объектов и сетевые задержки |
| Публичный GET-ответ | HTTP-кеш | Повторный запрос может не попасть на сервер | Заголовки, персонализацию и срок хранения |
| Статика и большие публичные файлы | CDN | Раздача с пограничного узла и снижение нагрузки на origin | Версионирование URL, очистку и правила доступа |
На практике слои комбинируют. Например, браузер и CDN отдают версионированный файл, приложение хранит результат дорогого запроса в Redis, а локальная память сохраняет небольшой объект на время одного процесса. Не включайте все уровни сразу: сначала измерьте, где возникает задержка и сколько запросов действительно повторяются.
Что ломается первым
Кеш устаревает после изменения данных
Это не баг конкретного Redis или CDN. Это отсутствие согласованной политики. Зафиксируйте для каждого типа данных: максимальный возраст, событие очистки и допустимое поведение при промахе. Для справочника можно принять временную неточность, для прав доступа — нет.
Кеш перегружает базу вместо разгрузки
При истечении одинакового TTL множество ключей может исчезнуть одновременно. Все запросы одновременно пойдут в базу — это cache stampede, или лавина промахов. Снизить риск помогают разнесённые сроки жизни, ограничение числа пересозданий и фоновый прогрев, но конкретный механизм зависит от используемого клиента Redis и фреймворка.
В кеш попадает неправильный вариант ответа
Причина обычно в слишком коротком ключе или неверно выбранных HTTP-заголовках. Проверьте запросы с разными пользователями, языками, ролями и параметрами. Тестируйте не только cache hit, но и отсутствие доступа к данным, которые были положены в кеш другим контекстом.
Система зависит от кеша сильнее, чем от базы
Кеш должен считаться производным хранилищем, если это не оговорено архитектурой отдельно. При недоступности Redis приложение должно либо обратиться к источнику, либо вернуть предсказуемую ошибку. Если без кеша сервис падает, у вас уже не кеширование, а скрытая база данных без полноценной стратегии восстановления.
Что измерять до и после
Не сравнивайте подходы по обещаниям документации. На тестовом стенде зафиксируйте версию приложения, тип хранилища, размер ответа, число параллельных запросов и долю попаданий в кеш. Затем измерьте p50, p95 и p99 задержки, количество запросов к базе, сетевой трафик, потребление памяти и время восстановления после очистки.
Для Redis отдельно наблюдайте промахи, ошибки соединения, время выполнения команд и объём памяти. Для HTTP-кеша и CDN проверяйте фактические заголовки ответа и долю запросов, которые не дошли до origin. Цифры до и после должны быть получены на вашем трафике: переносить результаты чужого проекта нельзя.
Что делать дальше
Составьте карту данных: какие ответы публичны, какие зависят от пользователя, сколько минут допустима устарелость и что должно происходить при недоступности кеша. Затем добавьте один слой, который закрывает измеренное узкое место, и поставьте мониторинг hit ratio, p95 задержки, ошибок хранилища и нагрузки на базу.
После этого проверьте сценарии релиза и отката: как меняются ключи, как очищаются старые объекты и что увидит пользователь сразу после публикации. Инвалидацию кеша и прогрев стоит разбирать отдельно — здесь важен выбор слоя и его цена.
Создатель презентаций: Структура и текст каждого слайда: заголовки-утверждения, одна мысль на слайд, заметки докладчику.
Спросить за 150 ₽Источники: Redis Documentation, MDN Web Docs: HTTP caching
Частые вопросы
Можно ли использовать только Redis и не настраивать HTTP-кеш?
Что выбрать для приложения с несколькими экземплярами?
Как не показать одному пользователю данные другого?
Какой TTL поставить для кеша?
Что будет, если Redis или CDN перестанет работать?
Нужно ли кешировать данные о правах доступа и балансе?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.