Time To Live
TTL 的本質是拿「資料新鮮度」去交換「系統速度、成本和穩定性」

第一步先看資料本身的更新頻率
- 商品名稱、分類這種通常很少改
- 庫存、價格、優惠活動可能常常變
- 使用者個人首頁資料可能又跟行為密切相關
TTL 本質上是根據資料變動速度來決定壽命。如果資料一天才改一次,你卻設 5 秒,快取幾乎沒價值,還會一直回源查資料庫。反過來,如果資料每分鐘都會變,你卻設 1 小時,使用者看到舊資料的機率就很高

不是所有資料都需要絕對即時。例如
- 最新新聞列表晚 30 秒更新,通常很多人能接受
- 商品庫存晚 10 分鐘更新,可能就會出事
- 交易餘額、付款狀態,如果延遲顯示就很危險
這一步重要,因為 TTL 設計真正要回答的是這份資料最久可以舊到什麼程度,業務還能接受。如果不先定義容忍度,你就會只靠感覺亂設 TTL。最後不是快取命中率太低,就是資料過期太久,兩邊都不討好。

- 資料更新很少,容忍延遲高 → TTL 可以長
- 資料更新很頻繁,容忍延遲低 → TTL 要短
資料更新頻繁,但讀多寫少,且可接受短暫舊資料 → 可以考慮中等 TTL
例如
- 地區列表:1 天
- 商品詳細頁:10 分鐘
- 熱門排行榜:1 分鐘
- 庫存:10 秒到 30 秒,甚至不靠 TTL,改用主動失效
- 使用者權限:幾分鐘內,且權限變更時要主動清掉

TTL 沒有標準答案,它永遠綁著業務場景

比較穩的做法常常是 TTL 當保底,而資料更新事件來時主動刪 cache,例如商品價格被修改時,直接清掉商品快取;這樣下一次讀取就會拿到新資料,而不是傻傻等 TTL 到期

根據 ttl 可能會預拉 30 min 後開始的活動
1 | var ongoingPromotions = await cacheManager.GetAsync( |
如果很多 key 都設一樣的 TTL,例如全部都 300 秒,可能在某個時間點一起失效,造成瞬間大量請求打回資料庫,這就是常見的快取雪崩。所以常會加一點隨機值 300 秒 ± 30 秒、600 秒 + random(0~120)
這樣做是為了把過期時間打散。不這樣做的話,系統平常很順,某個整點或尖峰時段卻突然被回源流量打爆,問題會很難查

TTL 設計不是設定完就結束,還要看
- cache hit rate 高不高
- 回源流量有沒有太大
- 使用者有沒有看到過舊資料資料庫
- 壓力有沒有下降
- 某些 key 是否特別容易失效後打爆後端

All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.


