Redis中的緩存穿透,緩存擊穿和緩存雪崩
概述
緩存擊穿、緩存穿透、緩存雪崩這三個問題是Reids在實際項目中會經常遇到問題,同時,這三個問題也是面試的熱點問題,下面,就本篇文章搞懂緩存穿透、緩存擊穿、緩存雪崩三大問題的原因及解決方法。
Redis在項目中作為緩存中間件是如何工作的?如圖所示

客戶端發起一個查詢請求的時候,首先去緩存中查詢,如果數據在緩存中存在,則直接將緩存中的數據返回給客戶端;如果數據在緩存中不存在,則繼續查詢數據庫,如果數據在數據庫中存在,則將該數據放入緩存中,并返回給客戶端,如果數據在數據庫中也不存在,則直接返回null給客戶端。
1.緩存穿透
1.1 什么是緩存穿透
緩存穿透是指查詢一個緩存中和數據庫中都不存在的數據,導致每次查詢這條數據都會透過緩存,直接查庫,最后返回空。當用戶使用這條不存在的數據瘋狂發起查詢請求的時候,對數據庫造成的壓力就非常大,甚至可能直接掛掉。這種情況的流程就變成下圖這樣了:

1.2 解決方案
解決緩存穿透的方法一般有兩種,第一種是緩存空對象,第二種是使用布隆過濾器。
1.2.1 緩存空對象
第一種方法比較好理解,就是當數據庫中查不到數據的時候,我緩存一個空對象,然后給這個空對象的緩存設置一個過期時間,這樣下次再查詢該數據的時候,就可以直接從緩存中拿到,從而達到了減小數據庫壓力的目的。
但這種解決方式有兩個缺點:
(1)需要緩存層提供更多的內存空間來緩存這些空對象,當這種空對象很多的時候,就會浪費更多的內存;
(2)會導致緩存層和存儲層的數據不一致,即使在緩存空對象時給它設置了一個很短的過期時間,那也會導致這一段時間內的數據不一致問題。
1.2.2 布隆過濾器
使用布隆過濾器,這是比較推薦的方法。所謂布隆過濾器,就是一種數據結構,它是由一個長度為m bit的位數組與n個hash函數組成的數據結構,位數組中每個元素的初始值都是0。在初始化布隆過濾器時,會先將所有key進行n次hash運算,這樣就可以得到n個位置,然后將這n個位置上的元素改為1。這樣,就相當于把所有的key保存到了布隆過濾器中了。
舉個例子,比如我們一共有3個key,我們對這3個key分別進行3次hash運算,key1經過三次hash運算后的結果分別為2/6/10,那么就把布隆過濾器中下標為2/6/10的元素值更新為1,然后再分別對key2和key3做同樣操作,結果如下圖:

這樣,當客戶端查詢時,也對查詢的key做3次hash運算得到3個位置,然后看布隆過濾器中對應位置元素的值是否為1,如果所有對應位置元素的值都為1,就證明key在庫中存在,則繼續向下查詢;如果3個位置中有任意一個位置的值不為1,那么就證明key在庫中不存在,直接返回客戶端空即可。如下圖:

當客戶端查詢key4時,key4的3次hash運算中,有一個位置8的值為0,就說明key4在庫中不存在,直接返回客戶端空即可。
所以,布隆過濾器就相當于一個位于客戶端與緩存層中間的攔截器一樣,負責判斷key是否在集合中存在。如下圖:

布隆過濾器的好處就是解決了第一種緩存空值的不足,但布隆過濾器也存在缺陷,
首先,它有誤判的可能,比如在上面客戶端查詢key4的圖中,假如key4經過3次hash運算得到的位置分別是2/4/6,由于這3個位置的值都是1,所以,布隆過濾器就認為key4在庫中存在,進而繼續向下查詢了。所以,布隆過濾器判斷存在的key實際上可能是不存在的,但布隆過濾器判斷不存在的key是一定不存在的。
它的第二個缺點就是刪除元素比較難,比如現在要刪除key2這個元素,那么需要將2/7/11三個位置的元素值改為0,但這樣就會影響到key1和key3的判斷。
2.緩存擊穿
2.1 什么是緩存擊穿
緩存擊穿是指當緩存中某個熱點數據過期了,在該熱點數據重新載入緩存之前,有大量的查詢請求穿過緩存,直接查詢數據庫。這種情況會導致數據庫壓力瞬間驟增,造成大量請求阻塞,甚至直接掛掉。

2.2 解決方案
解決緩存擊穿的方法也有兩種,第一種是設置key永不過期;第二種是使用分布式鎖,保證同一時刻只能有一個查詢請求重新加載熱點數據到緩存中,這樣,其他的線程只需等待該線程運行完畢,即可重新從Redis中獲取數據。
2.2.1 熱點Key值永不過期
第一種方式比較簡單,在設置熱點key的時候,不給key設置過期時間即可。不過還有另外一種方式也可以達到key不過期的目的,就是正常給key設置過期時間,不過在后臺同時啟一個定時任務去定時地更新這個緩存。

2.2.2 分布式鎖并發更新
第二種方式使用了加鎖的方式,鎖的對象就是key,這樣,當大量查詢同一個key的請求并發進來時,只能有一個請求獲取到鎖,然后獲取到鎖的線程查詢數據庫,然后將結果放入到緩存中,然后釋放鎖,此時,其他處于鎖等待的請求即可繼續執行,由于此時緩存中已經有了數據,所以直接從緩存中獲取到數據返回,并不會查詢數據庫。

3.緩存雪崩
3.1 什么是緩存雪崩
緩存雪崩是指當緩存中有大量的key在同一時刻過期,或者Redis直接宕機了,導致大量的查詢請求全部到達數據庫,造成數據庫查詢壓力驟增,甚至直接掛掉。

3.2 解決方案
針對第一種大量key同時過期的情況,解決起來比較簡單,只需要將每個key的過期時間打散即可,使它們的失效點盡可能均勻分布。
針對第二種redis發生故障的情況,部署redis時可以使用redis的幾種高可用方案部署
除了上面兩種解決方式,還可以使用其他策略,比如設置key永不過期、加分布式鎖等。

浙公網安備 33010602011771號