天天看點

Redis - 緩存穿透與雪崩

Redis緩存的使用,極大的提升了應用程式的性能和效率,特别是資料查詢方面。但同時,它也帶來了一 些問題。其中,最要害的問題,就是資料的一緻性問題,從嚴格意義上講,這個問題無解。如果對資料 的一緻性要求很高,那麼就不能使用緩存。

另外的一些典型問題就是,緩存穿透、緩存雪崩和緩存擊穿。目前,業界也都有比較流行的解決方案。

Redis - 緩存穿透與雪崩

一、緩存穿透(查不到)

1)概念

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

2)解決方案

● 布隆過濾器

布隆過濾器是一種資料結構,對所有可能查詢的參數以hash形式存儲,在控制層先進行校驗,不符合則 丢棄,進而避免了對底層存儲系統的查詢壓力;      
Redis - 緩存穿透與雪崩

● 緩存空對象

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

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

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

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

二、緩存擊穿(量太大,緩存過期!)

1)概述

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

當某個key在過期的瞬間,有大量的請求并發通路,這類資料一般是熱點資料,由于緩存過期,會同時訪 問資料庫來查詢最新資料,并且回寫緩存,會導使資料庫瞬間壓力過大。

設定熱點資料永不過期

從緩存層面來看,沒有設定過期時間,是以不會出現熱點 key 過期後産生的問題。      

加互斥鎖

分布式鎖:使用分布式鎖,保證對于每個key同時隻有一個線程去查詢後端服務,其他線程沒有獲得分布 式鎖的權限,是以隻需要等待即可。這種方式将高并發的壓力轉移到了分布式鎖,是以對分布式鎖的考 驗很大。      
Redis - 緩存穿透與雪崩

三、緩存雪崩

緩存雪崩,是指在某一個時間段,緩存集中過期失效。Redis 當機!

産生雪崩的原因之一,比如 馬上就要到雙十二零點,很快就會迎來一波搶購,這波商品時間比較集中的放入了緩存,假設緩存一個小時。那麼到了淩晨一點鐘的時候,這批商品的緩存就都過期了。而對這批商品的通路查詢,都落到了資料庫上,對于資料庫而言,就會産生周期性的壓力波峰。于是所有的請求都會達到存儲層,存儲層的調用量會暴增,造成存儲層也會挂掉的情況。

Redis - 緩存穿透與雪崩

其實集中過期,倒不是非常緻命,比較緻命的緩存雪崩,是緩存伺服器某個節點當機或斷網。因為自然 形成的緩存雪崩,一定是在某個時間段集中建立緩存,這個時候,資料庫也是可以頂住壓力的。無非就 是對資料庫産生周期性的壓力而已。而緩存服務節點的當機,對資料庫伺服器造成的壓力是不可預知 的,很有可能瞬間就把資料庫壓垮。

● redis高可用

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

● 限流降級

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

● 資料預熱

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