快取穿透、快取擊穿、快取雪崩區別

初仰發表於2024-03-14

高併發下快取雪崩
Redis中的資料大面積失效(時間過期)的情景

快取雪崩是指在我們設定快取時採用了相同的過期時間,導致快取在某一時刻同時失效,請求全部轉發到 DB,DB 瞬時壓力過重雪崩。
解決方案:
均勻過期:給熱點資料設定不同的過期時間,給每個key的失效時間加一個隨機值;
原有的失效時間基礎上增加一個隨機值,比如 1-5 分鐘隨機,這樣每一個快取的過期時間的重複率就會降低,就很難引發集體失效的事件。
設定熱點資料永不過期:不設定失效時間,有更新的話,需要更新快取;
服務降級:指服務針對不同的資料採用不同的處理方式:
業務訪問的是非核心資料,直接返回預定義資訊、空值或者報錯;
業務訪問核心資料,則允許訪問快取,如果快取缺失,可以讀取資料庫。
Redis 快取例項發生故障當機的場景

實現服務熔斷或者請求限流機制
透過監測Redis以及資料庫例項所在伺服器負載指標,如果發現Redis服務當機,導致資料庫的負載壓力增大,我們可以啟動服務熔斷機制,暫停對快取服務的訪問。
但是這種方法對業務應用的影響比較大,我們也可以透過限流的方式降低這種影響。
舉個例子:比如業務系統正常執行時,請求入口每秒最大允許進入的請求數是1萬個,其中9000請求個可以被快取處理,餘下1000個會傳送給資料庫處理。一旦發生雪崩,資料庫每秒處理的請求突然增加到1萬個,此時我們就可以啟動限流機制。在前端請求入口處,只允許每秒進入1000個請求,其他的直接拒絕掉。這樣就可以避免大量併發請求傳送給資料庫。

事前預防
透過主從節點的方式構建 Redis 快取高可靠叢集。 如果 Redis 快取的主節點故障當機了,從節點還可以切換成為主節點,繼續提供快取服務,避免了由於快取例項當機而導致的快取雪崩問題。
高併發下快取穿透
就是去查詢一個一定不存在的資料

快取穿透是指查詢一個一定不存在的資料,由於快取是不命中,將去查詢資料庫,但是資料庫也無此記錄,我們沒有將這次查詢的 null 寫入快取,這將導致這個不存在的資料每次請求都要到儲存層去查詢,失去了快取的意義。
在流量大時,可能 DB 就掛掉了,要是有人利用不存在的 key 頻繁攻擊我們的應用,這就是漏洞。
解決方案:
快取空結果、並且設定短的過期時間。(null結果進行快取)
如果有大量的Key穿透,快取空物件會佔用寶貴的記憶體空間。針對這種情況可以給空物件設定過期時間。
設定過期時間之後,可能會有快取與資料庫不一致的情況(後期可能又有這個條資料了)。
布隆過濾:快速判斷資料是否存在,避免從資料庫中查詢資料是否存在,減輕資料庫壓力。
介面層增加校驗:使用者鑑權、引數校驗(請求引數是否合法、請求欄位是否不存在等等。
高併發下快取擊穿
一個key過期,但是被高訪問,連續不斷的訪問可能會快取擊穿

對於一些設定了過期時間的 key,如果這些 key 可能會在某些時間點被超高併發地訪問,是一種非常“熱點”的資料。
這個時候,需要考慮一個問題:如果這個 key 在大量請求同時進來前正好失效,那麼所有對這個 key 的資料查詢都落到 db,我們稱為快取擊穿。
解決方案:
設定熱點資料永不過期:不設定失效時間,有更新的話,需要更新快取;
加互斥鎖:單機可以使用synchronized、lock,分散式可以使用lua指令碼或分散式鎖Redisson。
zookeeper與etcd,用來做鎖都比redis要好很多

相關文章