首頁  >  文章  >  資料庫  >  如何解決Redis緩存雪崩、擊穿與穿透

如何解決Redis緩存雪崩、擊穿與穿透

WBOY
WBOY轉載
2022-11-03 17:23:551616瀏覽

這篇文章為大家帶來了關於Redis的相關知識,其中主要介紹了關於怎麼解決redis緩存雪崩、擊穿與穿透的相關問題,緩存雪崩是指大量的請求無法命中Redis中的快取數據,也就是在Redis找不到數據了;下面一起來看一下,希望對大家有幫助。

如何解決Redis緩存雪崩、擊穿與穿透

推薦學習:Redis影片教學

#一、快取雪崩

1. 什麼是緩存雪崩?

快取雪崩是指大量的請求無法命中Redis中的快取數據,也就是在Redis找不到數據了,那業務系統只能到資料庫中查詢,進而導致所有的請求都傳送到了資料庫。如下圖所示:

資料庫不像Redis能處理大量請求,由快取雪崩導致的請求激增必須會導致資料庫所在宕機,這樣勢必會影響業務系統,所以如果發生緩存雪崩,對於業務系統肯定是致命的。

2. 為什麼發會生緩存雪崩?

什麼情況下出現快取雪崩呢?總結起來有以下兩個面向的原因:

  • 大量Redis快取資料同時過期,導致所有的發送到Redis請求都無法命中數據,只能到資料庫中進行查詢。

  • Redis伺服器宕機,所有請求都無法經Redis來處理,只能轉向資料庫查詢資料。

3. 如何避免快取雪崩?

針對導致快取雪崩的原因,有不同的解決方法:

  • 針對大量快取隨機過期時間,解決方法就是在原始過期時間的基礎上,再加上一個隨機過期時間,例如1到5分鐘之間的隨機過期時間,這樣可以避免大量的快取資料在同一時間過期。

  • 而針對Redis解決當機的導致的快取雪崩,可以提前搭建好Redis的主從伺服器進行資料同步,並配置哨兵機制,這樣在Redis伺服器因為宕機而無法提供服務時,可以由哨兵將Redis從伺服器設定為主伺服器,繼續提供服務。

二、快取擊穿

1. 什麼是快取擊穿

快取擊穿與快取雪崩的情況相似,雪崩是因為大量的資料過期,而快取擊穿則是指熱點資料過期,所有針對熱點資料的請求都需要到資料庫中處理,如下圖所示:

##2 . 怎麼避免快取擊穿?

解決快取擊穿的三種方式:

    不設定過期時間
如果我們能事先知道某個數據是熱點數據,那麼就可以不設定這些資料的過期,從而避免快取擊穿問題,例如一些秒殺活動的商品,在秒殺時會大量用戶訪問,這時候我們就可以將這些用於秒殺的商品資料提前寫入快取並且不設定過期時間。

    互斥鎖
提前知道某些資料會有大量訪問,我們當然可以設定不過期,但更多時候,我們並不能提前預知,這種情況要怎麼處理呢?

我們來分析快取擊穿的情況:

正常情況下,當某個

Redis快取資料過期時,如果有對該資料的請求,則重新到資料庫中查詢並再寫入緩存,讓後續的請求可以命中該快取而無須再去資料庫中查詢。

而熱點資料過期時,由於大量請求,當某個請求無法命中快取時,會去查詢資料庫並重新把資料寫入

Redis,也就是在寫入Redis之前,其他要求進來,也會去查詢資料庫。

好了,我們知道熱點資料過期後,很多請求會去查詢資料庫,那麼我們可以給去查詢資料庫的業務邏輯加個互斥鎖,只有獲得鎖的請求才能去查詢資料庫並把資料寫回

Redis,而其他沒有獲得鎖定的請求只能等待資料就緒。

上述步驟的如下圖所示:

#

  • 設定邏輯過期時間

使用互斥鎖雖然可以非常簡單地解決快取擊穿問題,但沒有獲得鎖的請求雖然排隊等待,這樣影響了系統的效能,還有另一種解決快取擊穿的方法就是在業務資料冗餘一個過期時間,例如下面的資料中我們增加了expire_at欄位用來表示資料過期時間。

{"name":"test","expire_at":"1599999999"}复制代码

這種方式的實作過程如下圖所示:

快取中的熱點資料中冗餘一個邏輯過期時間,但資料在Redis不設定過期時間

當一個請求拿到Redis中的資料時,判斷邏輯過期時間是否到期,如果沒有到期,直接傳回,如果到期則開啟另一個執行緒取得鎖定後去查詢資料庫並將查詢的最新資料寫回Redis,而目前請求傳回已查詢的資料。

三、快取穿透

1. 什麼是快取穿透

快取穿透是指要尋找的資料既不在快取當中,也不在資料庫中,因為不在快取中,所以請求一定會到達資料庫,Redis快取形同虛設,如下圖所示:

##2. 為什麼會發生快取穿透

在什麼條件下會發生快取穿透呢?主要有以下三種情況:

  • 用戶惡意攻擊請求

  • #錯誤操作把

    Redis和資料庫裡的數據刪除了

  • 用戶還未產生內容時,例如用戶的文章列表,用戶還未寫文章,所以快取和資料庫都沒有資料

3. 如何避免快取穿透?

a. 快取空值或預設值

當在

Redis快取中查詢不到資料時,再從資料庫查詢,如果同樣沒有數據,就直接快取一個空間或缺省值,這樣可以避免下次再去查詢資料庫;不過為了防止之後已經資料庫已經對應資料庫,再回傳空值問題,應該為快取設定過期時間,或是在產生資料時直接清除對應的快取空值。

b. 布隆過濾器

雖然快取空值可以解決快取穿透問題,但仍然需要查詢一次資料庫才能確定是否有數據,如果有用戶惡意攻擊,高並發地使用系統不存在的資料id進行查詢,所有的查詢都要經過資料庫,這樣仍然會給資料庫帶來很大的壓力。

所以,有沒有不用查詢資料庫就能確定資料是否存在的辦法呢?有的,用

布隆過濾器

布林過濾器主要是兩個部分:bit數組N個雜湊函數,其原理為:

  • 使用N個雜湊函數對要標記的數據進行哈希值計算。

  • 將計算到的雜湊值對bit數組的長度取模,這樣就可以得到每個哈希值在bit數組的位置。

  • 把bit數組中對應的位置標記為1。

下面是布隆過濾器原理示意圖:

#當要進行資料寫入時,執行述述步驟,計算對應bit數組位置並標識為1,那麼執行查詢時,就能查詢該資料是否存在了。

另外,由於哈希碰撞問題導致的誤差,所以不存在的資料經過布隆過濾器後,會被判定為存在,再去查資料庫,不過哈希碰到的機率很小,用布隆過濾器已經能幫我們攔截大部分的穿透要求了。

Redis本身就支援布隆過濾器,所以我們可以直接使用Redis布隆過濾器,而不用自己去實現,非常方便。

四、小結

快取的雪崩、擊穿、穿透是在業務應用快取時經常會碰到的快取異常問題,其原因與解決方法如以下表示所示:

問題原因解決方法##快取雪崩Redis #快取擊穿快取穿透Redis推薦學習:
大量資料過期或伺服器宕機#1. 隨機過期時間 2. 主從哨兵的叢集
熱點資料過期 1. 不設定過期時間2. 加上互斥鎖定3.冗餘邏輯過期時間
請求資料庫和都沒有的資料1. 快取空值或預設值2. 布隆過濾器
Redis影片教學

#

以上是如何解決Redis緩存雪崩、擊穿與穿透的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:juejin.im。如有侵權,請聯絡admin@php.cn刪除