上一篇說快取是一筆貸款。這篇把利息單一條條攤開——因為「加了 cache 之後反而更慘」不是罕見事故,是每一條都有名字的常見病。認得它們的長相,你才知道自己簽了什麼。

翻車一:資料不一致——使用者看到「已經不存在的東西」

最基本的一條,上一篇提過,這裡講它實際咬人的樣子。

商品下架了,DB 更新了,但快取裡那份還有 4 分鐘才過期——這 4 分鐘內,使用者看得到、點得進、甚至下了單,客服接到「明明有貨怎麼說沒貨」的電話。DB 是對的、快取也「沒壞」,但系統整體在說謊。

要害在於:不一致不是 bug,是快取的本性。你能做的只有選擇「容忍多久」(TTL 短一點)或「主動失效」(資料一改就刪快取)——而主動失效有多難,是下一篇整篇的主題。

翻車二:雪崩(cache stampede)——快取失效的瞬間,DB 被踩死

想像那個熱門排行榜快取,每 5 分鐘過期一次。過期的那一瞬間,正好有 500 個請求同時進來——500 個都發現快取沒東西,500 個同時衝去 DB 算那個很重的查詢

DB 平常只承受「每 5 分鐘一次」的重查詢,現在瞬間來 500 發。它跪了,其他本來好好的查詢跟著全部變慢,整個站一起下去。最諷刺的是:這災難只在「有快取」的系統發生——沒快取的話,這 500 個請求本來就是分散到 DB 的日常,反而不會同一毫秒集中爆發。

辨認方法:規律性的週期抖動——每隔一個 TTL 的長度,DB 負載就尖一下。解法方向(鎖住只讓一人重算、TTL 加隨機值錯開、過期前背景先刷新)留給災難模式的專文,這裡先讓你認得病。

翻車三:miss 比「沒有快取」更慢

反直覺但真實:快取沒中(miss)的請求,走的路是「查快取(落空)→ 查 DB → 寫回快取」——三段,比沒有快取的「查 DB」一段多兩次網路往返

平常 hit 率 95%,多出來的成本被 95% 的秒回攤掉,沒人在意。但兩種情況會讓它現形:

  • 重啟後的冷啟動:部署完快取全空,那幾分鐘每個請求都走三段路,全站比沒快取還慢——使用者剛好在你部署後湧入,體感就是「一更新就變卡」。
  • hit 率其實很低:例如把「每個使用者各自的訂單列表」拿去快取,每人只看自己的一次——幾乎每次都 miss,你付了三段路的錢,買到 0 的重用。快取只值得給「會被重複要的東西」,這判斷比技術本身重要。

辨認方法:看 hit rate。沒在監控 hit rate 的快取,等於不知道自己這筆貸款的利率。用 Redis 的話,現在就能查:

redis-cli INFO stats | grep keyspace
# keyspace_hits 與 keyspace_misses 兩個數字一除,就是你的 hit rate

翻車四:debug 難度翻倍——「到底是誰給的這個值?」

沒快取的時代,資料不對就查 DB,一條線。有快取之後,每個「畫面怪怪的」都要先問一輪:是 DB 錯?是快取舊?是哪一層快取舊(瀏覽器?CDN?Redis?)?剛剛有人清過快取嗎?

具體的痛:測試環境改了資料看不到效果,工程師懷疑自己 code 寫錯,查了半小時發現是快取沒清。這種「假 bug」每週偷走的時間,都是當初「加個 cache 很快啊」沒算進去的成本。

實務緩解:讓快取可觀察——key 的命名有規則(一看就知道存什麼)、後台有「查某個 key 現在的值」跟「手動清掉」的工具。debug 時第一句問「先清快取再看一次」,能省一半冤枉路。

收:什麼時候這些利息付得起?

四條利息全部指向同一個判斷:上一篇的「先有痛才加」不是雞湯,是精算。DB 真的在痛、資料真的會被重複讀、你真的有監控 hit rate——三個條件都成立,利息才划算。缺一個,你就是在用四種新病換一種舊病。

我自己被咬的那次是複合災難,比教科書難看得多。之前工作上維護的站,cache 上了、DB connection 有降但遠不如預期,當時只覺得「大概就這樣吧」。然後有人寫爬蟲來掃站——當時還沒上 rate limit,門是敞開的;爬蟲掃的多是長尾甚至根本不存在的資料,每一發都 miss、直穿 DB,而且查無資料連「寫回快取」的機會都沒有。更慘的是站上其他有快取的地方,TTL 訂在重複的時間點,同一瞬間集體過期——本來就被爬蟲壓著的 DB 又迎來一波集中重算,連線時間拉爆,DB 就炸了。

事後攤開來看,這一次事故裡就有三個洞:沒有 rate limit、TTL 沒錯開、查無資料沒設計。每個洞單獨看都是這篇利息單上的一條,我們是一次繳清、全部學會的。

後來這些洞在後台一個個補上:rate limit、錯開的 TTL、查無資料也給快取。補的過程還多繳了一筆學費——空值快取的 TTL 要跟一般資料分開規劃,而且要短得多。我們一開始沒特別設定,讓空值跟正常資料活得一樣久,帳單飆到嚇人才發現這件事:爬蟲掃過的每一個「不存在」都變成一筆佔著記憶體的快取,量大到錢包先於監控告警。

接下來往哪走