Настройка многоуровневого кэширования (Browser → CDN → Varnish → Redis → DB)
Многоуровневое кэширование снижает время ответа и нагрузку на базу данных за счёт последовательных слоёв хранения. Каждый уровень обслуживает запросы без передачи их на следующий — чем раньше попадание в кэш, тем быстрее ответ.
Схема уровней
Browser Cache (0ms)
↓ miss
CDN (5-30ms, edge nodes)
↓ miss
Varnish (1-5ms, application layer)
↓ miss
Redis (1-5ms, application cache)
↓ miss
Database (5-100ms)
Уровень 1: Browser Cache
# nginx: заголовки для браузерного кэша
location ~* \.(jpg|jpeg|png|gif|ico|css|js|woff2)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
# HTML страницы — не кэшировать в браузере, но разрешить CDN
location ~* \.html$ {
add_header Cache-Control "public, max-age=0, s-maxage=300";
add_header Vary "Accept-Encoding, Accept-Language";
}
# API responses
location /api/ {
add_header Cache-Control "private, no-store";
}
immutable — браузер не делает conditional requests для файлов с версионными хэшами.
Уровень 2: CDN (Cloudflare / CloudFront)
# cloudflare page rules
- pattern: "*.company.com/assets/*"
settings:
cache_level: cache_everything
edge_cache_ttl: 2592000 # 30 дней
browser_cache_ttl: 31536000 # 1 год
- pattern: "*.company.com/*.html"
settings:
cache_level: cache_everything
edge_cache_ttl: 300
browser_cache_ttl: 0
CloudFront invalidation при деплое:
aws cloudfront create-invalidation \
--distribution-id $DISTRIBUTION_ID \
--paths "/assets/*" "/*.html" "/sitemap.xml"
Уровень 3: Varnish
# /etc/varnish/default.vcl
vcl 4.1;
backend default {
.host = "app-server";
.port = "8080";
.probe = {
.url = "/health";
.timeout = 1s;
.interval = 5s;
.window = 5;
.threshold = 3;
}
}
sub vcl_recv {
# Не кэшировать авторизованные запросы
if (req.http.Authorization || req.http.Cookie ~ "session") {
return (pass);
}
# Не кэшировать POST/PUT/DELETE
if (req.method != "GET" && req.method != "HEAD") {
return (pass);
}
# Удалить ненужные cookies для кэшируемых страниц
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;
}
# Grace period — возвращать устаревший кэш при недоступности backend
set beresp.grace = 1h;
}
sub vcl_deliver {
if (obj.hits > 0) {
set resp.http.X-Cache = "HIT";
} else {
set resp.http.X-Cache = "MISS";
}
set resp.http.X-Cache-Hits = obj.hits;
}
Инвалидация через PURGE:
curl -X PURGE -H "Host: company.com" http://varnish:6081/page/about
Уровень 4: Redis
from redis import Redis
import json, hashlib
redis = Redis(host='redis', decode_responses=True)
class MultiLevelCache:
def get(self, key: str, db_fn, ttl: int = 300):
# L1: Redis
cached = redis.get(f"cache:{key}")
if cached:
return json.loads(cached), 'redis'
# L2: Database
data = db_fn()
if data is not None:
redis.setex(f"cache:{key}", ttl, json.dumps(data))
return data, 'db'
def invalidate(self, key: str):
redis.delete(f"cache:{key}")
# Инвалидировать Varnish
self._purge_varnish(key)
def _purge_varnish(self, path: str):
import requests
try:
requests.request('PURGE', f"http://varnish:6081{path}",
headers={'Host': 'company.com'}, timeout=2)
except:
pass
Координация инвалидации между уровнями
При изменении данных нужно инвалидировать все уровни:
def on_product_updated(product_id):
# Redis
redis.delete(f"product:{product_id}")
redis.delete(f"category_products:{product.category_id}")
# Varnish (HTTP PURGE)
purge_varnish(f"/products/{product_id}")
purge_varnish(f"/categories/{product.category_id}")
# CDN (Cloudflare Cache Tag)
cloudflare_purge_by_tag(f"product-{product_id}")
cloudflare_purge_by_tag(f"category-{product.category_id}")
Cloudflare Cache Tags (требуется Enterprise или Cache Rules):
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}"]}
)
Мониторинг hit rate по уровням
# Varnish
varnish_main_cache_hit / (varnish_main_cache_hit + varnish_main_cache_miss)
# Redis
redis_keyspace_hits_total / (redis_keyspace_hits_total + redis_keyspace_misses_total)
# CDN: через API Cloudflare Analytics / CloudFront metrics
Целевые показатели:
- Browser cache hit rate: >60% для статики
- CDN hit rate: >80% для публичных страниц
- Varnish hit rate: >70% для HTML
- Redis hit rate: >85% для данных
Срок выполнения
Настройка полного стека Browser→CDN→Varnish→Redis — 4–7 рабочих дней. Включая настройку инвалидации, мониторинга и нагрузочное тестирование.







