Уровни кеширования: браузер, CDN, reverse proxy и кеш приложения
Основы4 минРедакция Innovialabs
Коротко
Кеш работает на четырёх уровнях — браузер, CDN, reverse proxy и приложение; статику кешируют максимально близко к пользователю, персональные данные — только в приложении, а главная сложность везде одна: вовремя сбросить устаревшее.
Где живёт кеш
Запрос пользователя проходит длинный путь: браузер → CDN → reverse proxy (например, nginx) → приложение → база данных. На каждом шаге ответ можно сохранить и в следующий раз отдать без похода дальше. Чем ближе к пользователю сработал кеш, тем быстрее ответ и тем меньше нагрузка на сервер.
| Уровень | Где находится | Что кешировать | Чем управляется |
|---|---|---|---|
| Браузер | На устройстве пользователя | JS, CSS, шрифты, картинки | Заголовки Cache-Control, ETag |
| CDN | Узлы по всему миру | Статика, публичные страницы | Заголовки + настройки CDN |
| Reverse proxy | Перед вашим приложением | Публичные HTML-страницы, ответы API | Конфиг nginx/Varnish |
| Приложение | Redis, Memcached, память процесса | Результаты запросов к БД, вычисления | Код приложения |
Браузер
Браузер решает, использовать ли сохранённый файл, по заголовкам ответа:
Cache-Control: max-age=...— сколько секунд файл считается свежим;immutable— файл никогда не изменится, перепроверять не нужно;no-cache— хранить можно, но перед использованием надо спросить сервер;no-store— не хранить вообще (для персональных и чувствительных данных);ETag/Last-Modified— позволяют серверу ответить304 Not Modifiedбез повторной передачи файла.
Рабочая схема: файлы с хешем в имени (app.3f9a1c.js) кешируются надолго с immutable, а HTML — с no-cache, чтобы пользователь сразу получал новую версию после деплоя. Современные сборщики добавляют хеши автоматически.
CDN
CDN хранит копии файлов на серверах в разных регионах и отдаёт их с ближайшего к пользователю узла.
- Отлично подходит для статики, изображений, видео, публичных страниц.
- Учитывает заголовки
Cache-Controlиs-maxage(отдельный срок для общих кешей). - Для сброса есть purge — по URL, по тегу или полностью.
Риск: CDN может закешировать то, что не должен, например страницу с данными авторизованного пользователя. Ответы с персональными данными помечайте private или no-store.
Reverse proxy
nginx или Varnish перед приложением может хранить готовые ответы и не дёргать backend на каждый запрос. Это особенно полезно для тяжёлых публичных страниц: каталог, статьи, лендинги.
proxy_cache_path /var/cache/nginx keys_zone=pages:10m max_size=1g inactive=60m;
server {
location / {
proxy_cache pages;
proxy_cache_valid 200 5m;
proxy_cache_bypass $cookie_session;
proxy_no_cache $cookie_session;
proxy_pass http://app;
}
}
Здесь страницы кешируются на 5 минут, а запросы с cookie сессии идут мимо кеша — так залогиненный пользователь не увидит чужие данные.
Кеш приложения
Внутри приложения кешируют то, что дорого получать: результаты медленных запросов к базе, ответы внешних API, сложные вычисления. Обычно используют Redis или Memcached, чтобы кеш был общим для всех экземпляров приложения.
Типичный паттерн — cache-aside: приложение сначала смотрит в кеш, при промахе идёт в базу и кладёт результат в кеш с TTL.
Стратегии инвалидации
Сбросить устаревший кеш — самая сложная часть. Основные подходы:
- TTL (время жизни). Просто и надёжно, но данные могут быть устаревшими до истечения срока.
- Версионирование ключей и URL. Новая версия файла — новое имя (хеш в имени), старый кеш просто перестаёт использоваться.
- Явный сброс при изменении. Обновили товар — удалили его ключ в Redis и сделали purge в CDN.
- stale-while-revalidate. Отдаём слегка устаревший ответ мгновенно и обновляем его в фоне.
Типичные ошибки
- Закешированный HTML без версионирования. После деплоя пользователи видят старую страницу со ссылками на удалённые файлы.
- Персональные данные в общем кеше. Самая опасная ошибка: один пользователь видит данные другого.
- Cache stampede. Популярный ключ истекает, и сотни запросов одновременно идут в базу. Помогают блокировки, случайный разброс TTL и stale-while-revalidate.
- Кеш как единственное хранилище. Redis может очиститься; данные должны восстанавливаться из основного источника.
- Кеширование всего подряд. Каждый уровень кеша — ещё одно место, где данные могут устареть. Кешируйте то, что реально тормозит.
Подробно о заголовках — в документации MDN по HTTP-кешированию.