引言
要了解緩存的這幾個相關問題,我們先以一個例子來引入:
有一個get請求:
api/news/getById/1
正常情況下對其申請訪問的流程如圖:
但若是如此,訪問增多或者受到攻擊時很容易受到以下問題
1 緩存穿透
1.1 造成原因
當查詢一個不存在的數據時,MySQL查詢不到數據,也不會直接寫入緩存,導致每次請求都會查詢數據庫
1.2 解決方案
1.2.1 方案一 緩存空數據
緩存空數據,查詢返回的數據為空,仍將該結果保存,也就是保存null數據
優點:簡單
缺點:消耗內存,且當數據庫中的數據更新后,可能使得緩存與數據庫中的數據不一致
1.2.2 方案二 布隆過濾器
先解釋一個概念:bitmap(位圖)
bitmap相當于一個以bit為單位組成的數組,每個單元只能存儲二進制數0或1
布隆過濾器作用:檢索一個元素是否在一個集合中
比如:
但是當數組大小有限時,就會出現類似哈希沖突的問題:
此時可以發現,如果id為3的數據不存在時,用布隆過濾器時會造成誤判
可以得出,數組越大,布隆過濾器誤差越小,但同時帶來更多的內存消耗
如何調整其誤判率呢?
可以通過Redisson或者Guava來設置誤判率,通常將誤判率設置在5%以下
2 緩存擊穿
2.1 造成原因
給某個key設置了過期時間,當該key過期時,恰好對其有大量并發請求,這些并發請求可能瞬間將數據庫壓垮
2.2 解決方案
2.2.1 方案一 互斥鎖
特點:數據強一致,性能差,可在銀行系統中使用
2.2.2 方案二 邏輯過期
特點:高可用,但不能保證數據完全一致
? ? ? ? ? ?性能優,可在秒殺功能中使用
3 緩存雪崩
3.1 造成原因
同一時段大量key同時失效或Reids服務器宕機,導致大量請求到達數據庫,給數據庫帶來巨大壓力
3.2 解決方案
1.給不同key的TTL添加隨機值
2.利用Redis集群提高服務可用性,如哨兵模式和集群模式
3.給緩存業務添加降級限流策略,如nginx或spring cloud gateway
4.給業務添加多級緩存,如Guava或Caffeine
給緩存業務添加降級限流策略可作為保底策略,穿透、擊穿、雪崩均適用