- Cache-aside (lazy loading): check cache → miss → fetch DB → write cache → return — pattern phổ biến nhất, code:
const cached = await redis.get(key); if (cached) return JSON.parse(cached); const data = await db.query(...); await redis.setex(key, 300, JSON.stringify(data)); return data. - Write-through: write cache + DB đồng thời — data luôn fresh nhưng write chậm hơn.
- Write-behind: write cache trước, async flush xuống DB — write rất nhanh nhưng risk mất data nếu cache crash.
- Cache invalidation strategies: TTL (đơn giản, chấp nhận stale data), event-based (on update → delete cache key), versioned keys (
user:${id}:v${version}). - TTL chọn sao cho: data thay đổi ít → TTL dài (1 giờ), data thay đổi nhiều → TTL ngắn (30s) hoặc invalidate on write.
- Cache warming: pre-populate cache khi startup để tránh cold start — gọi
warmCache()sau khi server start. - Thundering herd problem: nhiều requests đồng thời hit expired key → tất cả cùng query DB → DB quá tải.
- Fix: probabilistic early expiration (renew cache trước khi hết hạn), mutex lock (chỉ 1 request query DB, còn lại chờ), stale-while-revalidate.
Pitfall: cache key collision — luôn dùng namespace ${service}:${resource}:${id}.