快取策略
規則
- 在每一層進行快取:瀏覽器(Cache-Control)、CDN(邊緣)、應用程式(Redis)、資料庫(查詢快取)
- 對可接受略為過時的內容使用
stale-while-revalidate —— 快速提供,在背景重新整理
- Cache-Control 標頭:對於有雜湊的靜態資源使用
public, max-age=31536000, immutable;對於動態頁面使用 public, s-maxage=60, stale-while-revalidate=300
- Redis 快取:序列化為 JSON,為每個鍵設定 TTL,使用命名空間鍵(
cache:users:123)
- React Query / TanStack Query:設定
staleTime(資料保持新鮮的時間長度)和 gcTime(保留在記憶體中的時間長度)
- 寫入時失效 —— 當資料變更時,立即刪除或更新快取項目
- 使用快取旁路模式:先檢查快取,未命中時從來源擷取,再寫入快取
- 對於 Next.js:利用 ISR(
revalidate)、unstable_cache 以及伺服器元件的 fetch 快取
- 基於標籤的失效:按實體類型標記快取項目,在變更時使該標籤的所有項目失效
模式
async function getCachedUser(id: string) {
const cached = await redis.get(`user:${id}`);
if (cached) return JSON.parse(cached);
const user = await db.user.findUnique({ where: { id } });
await redis.set(`user:${id}`, JSON.stringify(user), "EX", 3600);
return user;
}
避免
- 沒有設定 TTL 的快取 —— 過時資料將無限期存在
- 在共用 CDN 快取中快取使用者特定資料 —— 使用
private 或 Vary 標頭
- 快取雪崩:使用鎖定或
stale-while-revalidate 來防止驚群效應(thundering herd)
- 快取錯誤回應 —— 僅快取成功的結果