Мы сталкивались с проектами, где каждый запрос к странице превращался в десятки SQL-запросов. Тормозил даже простой блог. После внедрения многоуровневого кэширования время ответа упало с 2000 мс до 80 мс, а нагрузка на базу снизилась на 95%. Клиенты существенно снижают затраты на инфраструктуру после такой оптимизации. Рассказываем, как построить такую систему.
Многоуровневое кэширование — это последовательность слоёв хранения ответов. Каждый слой обслуживает запрос, не передавая его дальше. Чем ближе к пользователю попадание в кэш, тем быстрее ответ. Правильная стратегия снижает нагрузку на базу данных и сервер приложения, а также улучшает Core Web Vitals.
Почему одного уровня недостаточно?
Браузерный кэш экономит трафик, но не помогает при первом визите. CDN ускоряет доставку статики, но для динамических страниц нужен более быстрый слой. Varnish — мощный reverse proxy, но не умеет хранить сложные структуры данных. Redis решает эту задачу, но требует оперативной памяти. Комбинация этих инструментов даёт максимальный эффект: типичный сайт после настройки получает hit rate >80% на CDN и >70% на Varnish.
| Уровень | Типичное время ответа | Целевой hit rate |
|---|---|---|
| Browser cache | 0 ms | >60% для статики |
| CDN | 5-30 ms | >80% для публичных страниц |
| Varnish | 1-5 ms | >70% для HTML |
| Redis | 1-5 ms | >85% для данных |
| Database | 5-100 ms | - |
Рекомендуемые TTL для разных типов контента
| Тип контента | Browser Cache | CDN | Varnish | Redis |
|---|---|---|---|---|
| Статика (css, js, img) | 1 год | 30 дней | не кэшируется | не кэшируется |
| HTML страницы | 0 (s-maxage=300) | 5 мин | 5 мин | не кэшируется |
| JSON API | не кэшируется | 1 мин | 1 мин | 5 мин |
| Сессии пользователей | не кэшируется | не кэшируется | не кэшируется | 30 мин |
Эти TTL нужно корректировать под частоту изменений контента. Для новостного портала HTML лучше кэшировать на 2 минуты, для корпоративного сайта — на час. Мы всегда проводим нагрузочное тестирование, чтобы удостовериться, что hit rate соответствует целевым значениям.
Как настроить браузерное кэширование?
# nginx: заголовки для браузерного кэша location ~* \.(jpg|jpeg|png|gif|ico|css|js|woff2)$ { expires 1y; add_header Cache-Control "public, immutable"; } location ~* \.html$ { add_header Cache-Control "public, max-age=0, s-maxage=300"; add_header Vary "Accept-Encoding, Accept-Language"; } Директива immutable говорит браузеру не проверять актуальность файла — он гарантированно не изменится. Это даёт мгновенную загрузку при повторных визитах.
Как подключить CDN?
# cloudflare page rules - pattern: "*.company.com/assets/*" settings: cache_level: cache_everything edge_cache_ttl: 2592000 # 30 дней browser_cache_ttl: 31536000 # 1 год CDN снимает нагрузку с origin и сокращает TTFB для географически удалённых пользователей.
Varnish: тонкая настройка
vcl 4.1; backend default { .host = "app-server"; .port = "8080"; } sub vcl_recv { if (req.http.Authorization || req.http.Cookie ~ "session") { return (pass); } if (req.method != "GET" && req.method != "HEAD") { return (pass); } unset req.http.Cookie; return (hash); } sub vcl_backend_response { if (beresp.status == 200 || beresp.status == 301) { if (beresp.http.Content-Type ~ "text/html") { set beresp.ttl = 5m; } else if (beresp.http.Content-Type ~ "application/json") { set beresp.ttl = 1m; } unset beresp.http.Set-Cookie; } set beresp.grace = 1h; } sub vcl_deliver { if (obj.hits > 0) { set resp.http.X-Cache = "HIT"; } else { set resp.http.X-Cache = "MISS"; } } Согласно документации Varnish Cache, grace period позволяет обслуживать устаревший кэш, когда backend недоступен, что повышает доступность. Hash key можно кастомизировать для разделения кэша по языкам или устройствам.
Как решить проблему инвалидации кэша?
Без правильной инвалидации пользователи увидят устаревшие данные. Мы проектируем единую систему: при изменении данных отправляются HTTP PURGE на Varnish, удаляются ключи Redis и очищаются теги CDN. Пример на Python:
def on_product_updated(product_id): redis.delete(f"product:{product_id}") requests.request('PURGE', f"http://varnish:6081/products/{product_id}") # Cloudflare purge by tag requests.post(f"https://api.cloudflare.com/client/v4/zones/{zone_id}/purge_cache", headers={"Authorization": f"Bearer {token}"}, json={"tags": [f"product-{product_id}"]}) Типичная ошибка — настройка слишком длинных TTL без механизма инвалидации. Мы рекомендуем использовать теги на CDN и PURGE на Varnish, чтобы гарантировать свежесть данных. В некоторых сценариях мы применяем Edge Functions для мгновенной инвалидации на границе сети.
Мониторинг hit rate по уровням
Используем Prometheus метрики: varnish_main_cache_hit / (varnish_main_cache_hit + varnish_main_cache_miss), redis_keyspace_hits_total / (redis_keyspace_hits_total + redis_keyspace_misses_total). Целевые значения указаны в таблице выше. Регулярный мониторинг позволяет своевременно корректировать TTL и выявлять проблемы с инвалидацией.
Что входит в работу?
- Аудит текущей архитектуры кэширования — анализируем логи nginx, конфиги Varnish, параметры Redis и структуру CDN.
- Настройка Browser Cache через nginx или .htaccess.
- Подключение CDN (Cloudflare, CloudFront) с правилами кэширования.
- Установка и конфигурация Varnish (4.1+) с правилами grace и hash.
- Настройка Redis (кластер, персистентность, eviction policy).
- Создание единой системы инвалидации с PURGE и API.
- Нагрузочное тестирование и оптимизация TTL.
- Документация и обучение команды.
Сроки и стоимость
Настройка полного стека — от 4 до 7 рабочих дней. Стоимость рассчитывается индивидуально и зависит от сложности проекта. Клиенты обычно окупают вложения за 2–3 месяца за счёт снижения затрат на серверы и повышения конверсии.
Частая ошибка: неправильная настройка TTL
Многие устанавливают одинаковые TTL для всех типов контента. Это приводит либо к избыточному кэшированию динамических данных, либо к слишком частой инвалидации статики. Мы подбираем TTL на основе частоты обновления контента: статика — на год, HTML — 5 минут, JSON API — 1 минута. После настройки проверяем hit rate и корректируем при необходимости.
Закажите аудит текущего кэширования — мы выявим узкие места и предложим оптимальную стратегию. Получите консультацию по настройке многоуровневого кэширования для вашего проекта.







