天天看點

redis緩存穿透和緩存雪崩的淺析以及解決方案

作為一個記憶體資料庫,redis也總是免不了有各種各樣的問題,這篇文章主要是針對其中兩個問題進行講解:緩存穿透和緩存雪崩。并給出一些解決方案。這兩個問題是基本問題也是面試常問問題。

一、緩存穿透

1、概念

緩存穿透的概念很簡單,使用者想要查詢一個資料,發現redis記憶體資料庫沒有,也就是緩存沒有命中,于是向持久層資料庫查詢。發現也沒有,于是本次查詢失敗。當使用者很多的時候,緩存都沒有命中,于是都去請求了持久層資料庫。這會給持久層資料庫造成很大的壓力,這時候就相當于出現了緩存穿透。

這裡需要注意和緩存擊穿的差別,緩存擊穿,是指一個key非常熱點,在不停的扛着大并發,大并發集中對這一個點進行通路,當這個key在失效的瞬間,持續的大并發就穿破緩存,直接請求資料庫,就像在一個屏障上鑿開了一個洞。

為了避免緩存穿透其實有很多種解決方案。下面介紹幾種。

2、解決方案

(1)布隆過濾器

布隆過濾器是一種資料結構,垃圾網站和正常網站加起來全世界據統計也有幾十億個。網警要過濾這些垃圾網站,總不能到資料庫裡面一個一個去比較吧,這就可以使用布隆過濾器。假設我們存儲一億個垃圾網站位址。

可以先有一億個二進制比特,然後網警用八個不同的随機數産生器(F1,F2, …,F8) 産生八個資訊指紋(f1, f2, …, f8)。接下來用一個随機數産生器 G 把這八個資訊指紋映射到 1 到1億中的八個自然數 g1, g2, …,g8。最後把這八個位置的二進制全部設定為一。過程如下:

redis緩存穿透和緩存雪崩的淺析以及解決方案

有一天網警查到了一個可疑的網站,想判斷一下是否是XX網站,首先将可疑網站通過哈希映射到1億個比特數組上的8個點。如果8個點的其中有一個點不為1,則可以判斷該元素一定不存在集合中。

那這個布隆過濾器是如何解決redis中的緩存穿透呢?很簡單首先也是對所有可能查詢的參數以hash形式存儲,當使用者想要查詢的時候,使用布隆過濾器發現不在集合中,就直接丢棄,不再對持久層查詢。

這個形式很簡單。

在這裡插入圖檔描述

2、緩存空對象

當存儲層不命中後,即使傳回的空對象也将其緩存起來,同時會設定一個過期時間,之後再通路這個資料将會從緩存中擷取,保護了後端資料源;

但是這種方法會存在兩個問題:

如果空值能夠被緩存起來,這就意味着緩存需要更多的空間存儲更多的鍵,因為這當中可能會有很多的空值的鍵;

即使對空值設定了過期時間,還是會存在緩存層和存儲層的資料會有一段時間視窗的不一緻,這對于需要保持一緻性的業務會有影響。

二、緩存雪崩

1、概念

緩存雪崩是指,緩存層出現了錯誤,不能正常工作了。于是所有的請求都會達到存儲層,存儲層的調用量會暴增,造成存儲層也會挂掉的情況。

redis緩存穿透和緩存雪崩的淺析以及解決方案

2、解決方案

(1)redis高可用

這個思想的含義是,既然redis有可能挂掉,那我多增設幾台redis,這樣一台挂掉之後其他的還可以繼續工作,其實就是搭建的叢集。

(2)限流降級

這個解決方案的思想是,在緩存失效後,通過加鎖或者隊列來控制讀資料庫寫緩存的線程數量。比如對某個key隻允許一個線程查詢資料和寫緩存,其他線程等待。

(3)資料預熱

資料加熱的含義就是在正式部署之前,我先把可能的資料先預先通路一遍,這樣部分可能大量通路的資料就會加載到緩存中。在即将發生大并發通路前手動觸發加載緩存不同的key,設定不同的過期時間,讓緩存失效的時間點盡量均勻。

繼續閱讀