Redis的緩存雪崩、緩存擊穿、緩存穿透與緩存預熱

一、緩存雪崩:

1、什麼是緩存雪崩:

如果緩在某一個時刻出現大規模的key失效,那麼就會導致大量的請求打在了數據庫上面,導致數據庫壓力巨大,如果在高併發的情況下,可能瞬間就會導致數據庫宕機。這時候如果運維馬上又重啓數據庫,馬上又會有新的流量把數據庫打死。這就是緩存雪崩。

2、問題分析:

造成緩存雪崩的關鍵在於同一時間的大規模的key失效,爲什麼會出現這個問題,主要有兩種可能:第一種是Redis宕機,第二種可能就是採用了相同的過期時間。搞清楚原因之後,那麼有什麼解決方案呢?

3、解決方案:

(1)事前:

① 在原有key的失效時間的基礎上,加上一個隨機值,比如1-5分鐘,這樣就可以避免相同的過期時間導致緩存雪崩,造成大量數據庫的訪問。

② 分級緩存,第一級緩存失效的基礎上,訪問二級緩存,每一級緩存的失效時間都不同。

③ 保證Redis緩存的高可用,防止Redis宕機導致緩存雪崩的問題。可以使用 主從+ 哨兵,Redis集羣來避免 Redis 全盤崩潰的情況。

(2)事中:

① 使用熔斷機制,限流降級。當流量達到一定的閾值,直接返回“系統擁擠”之類的提示,防止過多的請求打在數據庫上將數據庫擊垮,至少能保證一部分用戶是可以正常使用,其他用戶多刷新幾次也能得到結果。

(3)事後:

① 開啓Redis持久化機制,儘快恢復緩存數據,一旦重啓,就能從磁盤上自動加載數據恢復內存中的數據。

 

二、緩存擊穿:

1、什麼是緩存擊穿:

緩存擊穿跟緩存雪崩有點類似,緩存雪崩是大規模的key失效,而緩存擊穿是某個熱點的key失效,大併發集中對其進行請求,就會造成大量請求讀緩存沒讀到數據,從而導致高併發訪問數據庫,引起數據庫壓力劇增。這種現象就叫做緩存擊穿。

2、問題分析:

關鍵在於某個熱點的key失效了,導致大併發集中打在數據庫上。所以要從兩個方面解決,第一是否可以考慮熱點key不設置過期時間,第二是否可以考慮降低打在數據庫上的請求數量。

3、解決方案:

(1)熱點數據緩存永遠不過期。

(2)在緩存失效後,通過互斥鎖或者隊列來控制讀數據寫緩存的線程數量,比如某個key只允許一個線程查詢數據和寫緩存,其他線程等待。這種方式會阻塞其他的線程,此時系統的吞吐量會下

 

三、緩存穿透:

1、什麼是緩存穿透:

大部分情況下,我們使用Redis都是通過Key查詢對應的值,假如發送的請求傳進來的key是不存在Redis中的,那麼就查不到緩存,查不到緩存就會去數據庫查詢。

假設大量的併發,或者有人惡意頻繁用一定不存在的key來訪問服務器,那麼每次請求都一定會打到數據庫上面去,這些請求像“穿透”了緩存一樣直接打在數據庫上,這種現象就叫做緩存穿透。嚴重情況下,可能導致數據庫承受不住而宕機崩潰。

2、問題分析:

緩存穿透的關鍵在於在Redis中查不到key值,它和緩存擊穿的根本區別在於傳進來的key在Redis中是不存在的。假如有黑客傳進大量的不存在的key,那麼大量的請求打在數據庫上是很致命的問題,所以在日常開發中要對參數做好校驗,一些非法的參數,不可能存在的key就直接返回錯誤提示。

3、解決方法:

(1)將無效的key存放進Redis中:

當出現Redis查不到數據,數據庫也查不到數據的情況,我們就把這個key保存到Redis中,設置value="null",並設置其過期時間極短,後面再出現查詢這個key的請求的時候,直接返回null,就不需要再查詢數據庫了。但這種處理方式是有問題的,假如傳進來的這個不存在的Key值每次都是隨機的,那存進Redis也沒有意義。

(2)使用布隆過濾器:

如果布隆過濾器判定某個 key 不存在布隆過濾器中,那麼就一定不存在,如果判定某個 key 存在,那麼很大可能是存在(存在一定的誤判率)。於是我們可以在緩存之前再加一個布隆過濾器,將數據庫中的所有key都存儲在布隆過濾器中,在查詢Redis前先去布隆過濾器查詢 key 是否存在,如果不存在就直接返回,不讓其訪問數據庫,從而避免了對底層存儲系統的查詢壓力。

如何選擇:針對一些惡意攻擊,攻擊帶過來的大量key是隨機,那麼我們採用第一種方案就會緩存大量不存在key的數據。那麼這種方案就不合適了,我們可以先對使用布隆過濾器方案進行過濾掉這些key。所以,針對這種key異常多、請求重複率比較低的數據,優先使用第二種方案直接過濾掉。而對於空數據的key有限的,重複率比較高的,則可優先採用第一種方式進行緩存。

 

四、緩存預熱:

1、什麼是緩存預熱:

緩存預熱是指系統上線後,提前將相關的緩存數據加載到緩存系統。避免在用戶請求的時候,先查詢數據庫,然後再將數據緩存的問題,用戶直接查詢事先被預熱的緩存數據。

2、緩存預熱解決方案:

(1)直接寫個緩存刷新頁面,上線時手工操作下

(2)數據量不大時,可以在項目啓動的時候自動進行加載

(3)定時刷新緩存

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章