天天看點

redis緩存穿透、緩存擊穿、緩存雪崩

緩存處理流程

      前台請求,背景先從緩存中取資料,取到直接傳回結果,取不到時從資料庫中取,資料庫取到更新緩存,并傳回結果,資料庫也沒取到,那直接傳回空結果。

redis緩存穿透、緩存擊穿、緩存雪崩

下面介紹redis緩存穿透、緩存擊穿、緩存雪崩和緩存當機。

緩存穿透

       緩存穿透是指緩存和資料庫中都沒有的資料,而使用者不斷發起請求,如發起為id為“-1”的資料或id為特别大不存在的資料。這時的使用者很可能是攻擊者,攻擊會導緻資料庫壓力過大。

布隆過濾器

接口層增加校驗,如使用者鑒權校驗,id做基礎校驗,id<=0的直接攔截;

從緩存取不到的資料,在資料庫中也沒有取到,這時也可以将key-value對寫為key-null,緩存有效時間可以設定短點,如30秒(設定太長會導緻正常情況也沒法使用)。這樣可以防止攻擊使用者反複用同一個id暴力攻擊

緩存擊穿

      緩存擊穿是指緩存中沒有但資料庫中有的資料(一般是緩存時間到期),這時由于并發使用者特别多,同時讀緩存沒讀到資料,又同時去資料庫去取資料,引起資料庫壓力瞬間增大,造成過大壓力

設定熱點資料永遠不過期。

加互斥鎖,互斥鎖參考代碼如下:

redis緩存穿透、緩存擊穿、緩存雪崩

代碼說明:

          1)緩存中有資料,直接走上述代碼13行後就傳回結果了

          2)緩存中沒有資料,第1個進入的線程,擷取鎖并從資料庫去取資料,沒釋放鎖之前,其他并行進入的線程會等待100ms,再重新去緩存取資料。(加鎖保證同一時刻隻有一個線程進入mysql,其餘線程等待,保證安全。)

          3)當然這是簡化處理,理論上如果能根據key值加鎖就更好了,就是線程a從資料庫取key1的資料并不妨礙線程b取key2的資料,上面代碼明顯做不到這點。

緩存雪崩

      緩存雪崩是指緩存中資料大批量到過期時間,而查詢資料量巨大,引起資料庫壓力過大甚至down機。

和緩存擊穿不同的是,緩存擊穿指并發查同一條資料,緩存雪崩是不同資料都過期了,很多資料都查不到進而查資料庫。

緩存資料的過期時間設定随機,防止同一時間大量資料過期現象發生。

如果緩存資料庫是分布式部署,将熱點資料均勻分布在不同搞得緩存資料庫中。

緩存當機

上面說到的場景是緩存依舊有效的,那麼當redis挂掉時,這個時候如何來應對大量的回源請求呢?先來說一種簡單的方式:

白名單顧名思義就是:在緩存當機之前的一段時間裡,會将請求的資料在系統中的有無,記錄在一個map中。當緩存當機後,首先在map中判斷是否含有資料,有則回源db,沒有的話就直接傳回結果。

這種方式實作起來比較簡單(demo就不提供了),但是占用的記憶體空間比較龐大。如一個value是10位元組,那麼要存儲大小為1億的map時,其所需的記憶體大小大約是:10 * 2 * 10e8 = 2g(假設map的使用率為50%)。

由此可見其對于一種類型的資料判斷就需要一個 2g 的map去操作,這種方式就不可行了。

對于緩存當機的場景,使用白名單可能會造成一定程度的誤判。原因是當機之前的緩存不一定能覆寫到所有db中的資料,當當機後使用者請求了一個以前從未請求的資料,這個時候就會産生誤判。

關于作者:大哥哥招牌coding

版權聲明:所有文章僅用于學習和交流目的,歡迎轉載,轉載請注明原文作者及出處。