Redis 面試 —— 緩存雪崩、緩存擊穿、緩存穿透

1、緩存雪崩

在給 key 設置過期時間的策略上沒有限制,給一大堆的 key 設置了相同的過期時間,當達到過期時間的時,在某一刻有一堆的 key 都被清除了,這個時候,新來的請求全部去數據庫請求,數據庫瞬時訪問壓力過重而扛不住的情況。假如這個時候掛的是一個用戶服務的數據庫,這個時候所有依賴這個庫的接口都會報錯,就算重啓,用戶的請求依舊會把數據庫搞掛,反覆來個幾次,用戶也不玩了。

解決辦法

最簡單的解決方法就是把緩存失效的時間分散開來,例如可以在本來的失效時間上增加一個隨機值,這樣就不會有大量的 key 在同一時刻失效了。

2、緩存擊穿

緩存擊穿有點像緩存雪崩,但是又有些不一樣,這種情況都是發生在設置了過期時間的 key,如果某個會過期的 key 在某個時間點可能被超高併發地訪問,就有可能發生這個問題。假如恰巧在 key 過期的時候,又有大量對這個 Key 的併發請求過來,這個時候發現緩存過期,便會去數據庫讀取數據,同樣因爲請求量過大而搞掛數據庫。

解決方法

1、可以設置熱點數據永遠不過期;例如 Redis 角度,不設置過期時間。

2、也可以加上互斥鎖,在緩存失效的時候(判斷拿出來的值爲空),不立即去數據庫讀取數據,先使用帶成功操作返回值的接口(比如 set 接口)獲取一把鎖,獲取鎖成功後,再去數據庫讀取數據,然後把讀到的數據設置到緩存裏,如果獲取鎖失敗,就重新讀 Redis 的緩存。

3、緩存穿透

當去 Redis 查詢一個一定不存在的 key 時,因爲緩存不會命中,就會去數據庫讀取,一般出於容錯的考慮,在數據庫查不到數據時,不會寫入 Redis 中,而這種查詢不存在的 key 時,每次請求都會跑去數據庫查詢,Redis 這層緩存就失去了意義。在流量大的時候,或者有人惡意使用不存在的 key 去查詢的時候,就會把數據庫搞掛。

解決方法

我記得華爲學習手冊裏面有這樣一種定義 —— 可信域、不可信域。對外提供的接口,因爲調用方不是自己的程序,不能確定調用者會爲這個接口傳遞什麼參數,所以傳遞的參數是不可信。大體是這樣描述,細節記不清楚了,基於這一條,加強對參數的校驗,從而屏蔽這種不可信可能造成的潛在危機。

上述的方法只是降低了緩存穿透的概率,並不能完全解決,所以還需要有一定的補充。當從 Redis 中取不到數據,且數據庫中也沒有數據,這時把這個 key 的 value 寫爲 null 或者什麼(根據具體情況而定),同時把緩存超時時間設置的短一點,避免由於設置過長導致的正常情況也沒法使用。

一般情況下,正常用戶,不會有意頻繁去嘗試無效 key 的請求,所以,可以讓運維人員設置每個 IP 每秒可以訪問次數的限制。

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