3大問題!Redis快取異常及處理方案總結

danny_2018發表於2022-06-21

Redis作為一個高效能的記憶體中的key-value資料結構儲存系統,在我們日常開發中廣泛應用於快取、計數器、訊息佇列、排行榜等場景中,尤其是作為最常用的快取方式,在提高資料查詢效率、保護資料庫等方面起到了不可磨滅的作用,但實際應用中,可能會出現一些Redis快取異常的情況,本文主要對Redis快取異常及處理方案進行了總結。

一、背景

Redis是一個完全開源的、遵守BSD協議的、高效能的key-value資料結構儲存系統,它支援資料的持久化,可以將記憶體中的資料儲存在磁碟中,而且不僅僅支援簡單的key-value型別的資料,同時還提供list,set,zset,hash等資料結構的儲存,功能十分強大,Redis還支援資料的備份,即master-slave模式的資料備份,從而提高可用性。當然最重要的還是讀寫速度快,作為我們平常開發中最常用的快取方案被廣泛應用。但在實際應用過程中,它會存在快取雪崩、快取擊穿和快取穿透等異常情況,如果忽視這些情況可能會帶來災難性的後果,下面主要對這些快取異常和常見處理方案進行相應分析與總結。

二、快取雪崩

(一)是什麼

一段時間內本應在redis快取中處理的大量請求,都傳送到了資料庫進行處理,導致對資料庫的壓力迅速增大,嚴重時甚至可能導致資料庫崩潰,從而導致整個系統崩潰,就像雪崩一樣,引發連鎖效應,所以叫快取雪崩。

(二)為什麼

出現上述情況的常見原因主要有以下兩點:

大量快取資料同時過期,導致本應請求到快取的需重新從資料庫中獲取資料。

redis本身出現故障,無法處理請求,那自然會再請求到資料庫那裡。

(三)怎麼辦

針對大量快取資料同時過期的情況:

實際設定過期時間時,應當儘量避免大量key同時過期的場景,如果真的有,那就透過隨機、微調、均勻設定等方式設定過期時間,從而避免同一時間過期。

新增互斥鎖,使得構建快取的操作不會在同一時間進行。

雙key策略,主key是原始快取,備key為複製快取,主key失效時,可以訪問備key,主key快取失效時間設定為短期,備key設定為長期。

後臺更新快取策略,採用定時任務或者訊息佇列的方式進行redis快取更新或移除等。

針對redis本身出現故障的情況:

在預防層面,可以透過主從節點的方式構建高可用的叢集,也就是實現主Redis例項掛掉後,能有其他從庫快速切換為主庫,繼續提供服務。

如果事情已經發生了,那就要為了防止資料庫被大量的請求搞崩潰,可以採用服務熔斷或者請求限流的方法。當然服務熔斷相對粗暴一些,停止服務直到redis服務恢復,請求限流相對溫和一些,保證一些請求可以處理,不是一刀切,不過還是看具體業務情況選擇合適的處理方案。

三、快取擊穿

(一)是什麼

快取擊穿一般出現在高併發系統中,是大量併發使用者同時請求到快取中沒有但資料庫中有的資料,也就是同時讀快取沒讀到資料,又同時去資料庫去取資料,引起資料庫壓力瞬間增大。和快取雪崩不同的是,快取擊穿指併發查同一條資料,快取雪崩是不同資料都過期了,很多資料都查不到從而查資料庫。

(二)為什麼

這種情況其實一般出現的原因就是某個熱點資料快取過期,由於是熱點資料,請求併發量又大,所以過期的時候還是會有大量請求同時過來,來不及更新快取就全部打到資料庫那邊了。

(三)怎麼辦

針對這種情況有兩種常見的處理方案:

簡單粗暴的對熱點資料不設定過期時間,這樣不會過期,自然也就不會出現上述情況了,如果後續想清理,可以透過後臺進行清理。

新增互斥鎖,即當過期之後,除了請求過來的第一個查詢的請求可以獲取到鎖請求到資料庫,並再次更新到快取中,其他的會被阻塞住,直到鎖被釋放,同時新的快取也被更新上去了,後續請求又會請求到快取上,這樣就不會出現快取擊穿了。

四、快取穿透

(一)是什麼

快取穿透是指資料既不在redis中,也不在資料庫中,這樣就導致每次請求過來的時候,在快取中找不到對應key之後,每次都還要去資料庫再查詢一遍,發現資料庫也沒有,相當於進行了兩次無用的查詢。這樣請求就可以繞過快取直接查資料庫,如果這個時候有人想惡意攻擊系統,就可以故意使用空值或者其他不存在的值進行頻繁請求,那麼就會對資料庫造成比較大的壓力。

(二)為什麼

這種現象的原因其實很好理解,業務邏輯裡面如果使用者對某些資訊還沒有進行相應的操作或者處理,那對應的存放資訊的資料庫或者快取中自然也就沒有相應的資料,也就容易出現上述問題。

(三)怎麼辦

針對快取穿透,一般有以下三種處理方案:

非法請求的限制,主要是指引數校驗、鑑權校驗等,從而一開始就把大量的非法請求攔截在外,這在實際業務開發中是必要的手段。

快取空值或者預設值,如果從快取取不到的資料,在資料庫中也沒有取到,那我們仍然把這個空結果進行快取,同時設定一個較短的過期時間。透過這個設定的預設值存放到快取,這樣第二次到快取中獲取就有值了,而不會繼續訪問資料庫,可以防止有大量惡意請求是反覆用同一個key進行攻擊。

使用布隆過濾器快速判斷資料是否存在。那什麼是布隆過濾器呢,簡單來說,就是可以引入了多個相互獨立的雜湊函式,保證在給定的空間和誤判率下,完成元素判重。因為我們知道,存在hash碰撞這樣一種情況,那如果只使用一個hash函式,則碰撞衝突的機率明顯會變大,那為了減少這種衝突,我們可以多引入幾個hash函式,而布隆過濾器演算法的核心思想就是利用多個不同的hash函式來解決這樣一種衝突。它的優點是空間效率高,查詢時間短,遠超其他演算法,而它的缺點就是會存在一定的誤識別率,它不能完全保證請求過來的key,透過布隆過濾器的校驗,就一定有這個資料,畢竟理論上還是會存在衝突情況,無論機率多小。但是,只要沒有透過布隆過濾器的校驗,那麼這個key就一定不存在,只要利用這一點其實就已經可以過濾掉大部分不存在的key的請求了,在正常場景下已然足夠了。

五、其他

除了上述三種常見的Redis快取異常問題之外,還經常聽到的有快取預熱和快取降級兩個名詞,與其說是異常問題,不如說是兩種的最佳化處理方法。

(一)快取預熱

快取預熱就是系統上線前後,將相關的快取資料直接載入到快取系統中去,而不依賴使用者。這樣就可以避免在使用者請求的時候,先查詢資料庫,然後再將資料快取的問題。使用者直接查詢事先被預熱的快取資料,這樣可以避免那麼系統上線初期,對於高併發的流量,都會訪問到資料庫中, 對資料庫造成流量的壓力。根據資料不同量級,可以有以下幾種做法:

資料量不大:專案啟動的時候自動進行載入。

資料量較大:後臺定時重新整理快取。

資料量極大:只針對熱點資料進行預載入快取操作。

(二)快取降級

快取降級是指當快取失效或快取服務出現問題時,為了防止快取服務故障,導致資料庫跟著一起發生雪崩問題,所以也不去訪問資料庫,但因為一些原因,仍然想要保證服務還是基本可用的,雖然肯定會是有損服務。因此,對於不重要的快取資料,我們可以採取服務降級策略。一般做法有以下兩種:

直接訪問記憶體部分的資料快取。

直接返回系統設定的預設值。

六、總結

本文主要對常見的Redis快取異常及其處理方案進行了總結,可以用下圖做個概括:

0

來自 “ K8S中文社群 ”, 原文作者:尹哲浩;原文連結:https://mp.weixin.qq.com/s/P38ETBZJO2lNlE-i7g6HhA,如有侵權,請聯絡管理員刪除。

相關文章