緩存穿透、緩存擊穿、緩存雪崩的區別


一、緩存穿透:(即:緩存無數據,數據庫也無數據)

  如黑客惡意攻擊,使用緩存和數據庫均沒有的key進行不斷請求,導致數據庫壓力過大。

解決方法:

1、對用戶進行鑒權、對請求參數進行校驗,不合理直接過濾。

2、對查詢不到的數據也放到緩存,value為空,設置一定的過期時間。(不太常用,因為如果是隨機key就不起作用,且占緩存)

3、使用布隆過濾器,快速判斷key是否在數據庫中存在,不存在直接返回。(最有效)

第1種是最常用的策略,第2種不太常用,因為如果是隨機key就不起作用,且占緩存,第三種最簡單有效。實際使用中,可以1、3相結合。

 

二、緩存擊穿:(即:緩存無數據,數據庫有數據,key比較集中)

  如高並發的情況下,熱點數據緩存過期,這時候會導致大量請求讀不到緩存同時讀數據庫,導致數據庫負載過大。

解決方法:

1、設置熱點數據永遠不過期。

2、熱點數據快過期時,通過另一個異步線程重新設置key。

3、當從緩存數據過期,重新從數據庫加載數據到緩存的過程上互斥鎖。

第1種的話,數據量大時,緩存量會比較大,第2種,很好理解,但是需要另外的邏輯去維護,會增加系統的復雜度。第3種,是比較常用的方式。

加載緩存時上互斥鎖:

 1     public String get(String key) throws Exception {
 2         String value = redis.get(key);
 3         // 緩存過期
 4         if (value == null) {
 5             // 設置有效期,防止del操作失敗時,緩存過期一直不能重新加載緩存
 6             if (redis.setnx(key_mutex, 1, 60)) {
 7                 // 從數據庫加載緩存
 8                 value = database.get(key);
 9                 redis.set(key, value, expire_time);
10                 redis.del(key_mutex);
11             } else {
12                 // 其他線程已經在加載緩存,等待並重新獲取即可
13                 sleep(50);
14                 get(key);
15             }
16         }
17         return value;
18     }

 

三、緩存雪崩:(即:緩存無數據,數據庫有數據,key比較分散)

  如在高並發的情況下,緩存同一時刻失效(如緩存掛了,或者設置了相同過期時間),所有請求會讀數據庫,容易導致數據庫負載瞬間上升,乃至崩掉。如果重啟數據庫,立馬又會被新的請求壓崩。

解決方法:

1、緩存的失效時間設置為隨機值,避免同時失效。

2、redis搭建高可用,主從+哨兵,redis cluster。

3、服務限流、降級,避免數據庫被瞬間壓崩。

第1種只能防止因緩存同時過期導致的緩存失效,第2種可以有效避免單台緩存掛掉的情況。第3種是通過提高服務的高可用,來避免緩存失效帶來的影響,是輔助措施。

 

緩存擊穿和緩存雪崩區別:

  兩者有點像,主要區別在於緩存擊穿是查詢同一條數據或熱點數據查詢不到,穿過了緩存。緩存雪崩是指大量數據查詢不到,穿過了緩存。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM