Cache-aside com Redis no catalog: hit ratio, p99, invalidação — e um stampede, reproduzido e corrigido
catalog
Quantas vezes "próximos eventos em São Paulo, página 1" é lido para cada vez que muda?
GET key ──► hit? ── yes ─► return (no DB) │ no ─► SELECT … ─► SET key value PX ttl ─► return
catalog:event:{id}
catalog:events:city=…:page=…
Se o cache absorvia 95% das leituras, a queda dele manda 20× a carga para o banco.
Um admin muda um preço. Por quanto tempo um fã pode ver o antigo, em cada página?
CACHE_ENABLED=false docker compose up -d && k6 run -e RATE=300 load/cache.js CACHE_ENABLED=true docker compose up -d && docker compose exec redis redis-cli FLUSHALL k6 run -e RATE=300 load/cache.js # cold k6 run -e RATE=300 load/cache.js # warm
X-Cache
cache_hit
latency_hit
latency_miss
CACHE_TTL_LIST=3s CACHE_STAMPEDE_PROTECTION=false docker compose up -d k6 run load/stampede.js # cache_misses ≫ expirations
miss ─► SET key:lock token NX PX 2000 ├─ won ─► re-check, load, SET, release └─ lost ─► poll the cache every 25 ms (≤ 500 ms)
Roteiro: (1) por que fazer cache do catálogo; (2) cache-aside; (3) chaves e TTLs; (4) tratamento de falhas; (5) a conta do hit ratio; (6) medição; (7) stampede e o lock; (8) outras curas.