溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

怎么解讀Redis緩存穿透、緩存擊穿和緩存雪崩

發(fā)布時間:2021-12-13 09:19:16 來源:億速云 閱讀:171 作者:柒染 欄目:大數據

怎么解讀Redis緩存穿透、緩存擊穿和緩存雪崩,很多新手對此不是很清楚,為了幫助大家解決這個難題,下面小編將為大家詳細講解,有這方面需求的人可以來學習下,希望你能有所收獲。

一、緩存穿透

1、概念

緩存穿透是指查詢一個數據庫一定不存在的數據。正常的使用緩存流程大致是,數據查詢先進行緩存查詢,如果key不存在或者key已經過期,再對數據庫進行查詢,并把查詢到的對象,放進緩存。如果數據庫查詢對象為空,則不放進緩存。

這里需要注意緩存擊穿的區(qū)別,緩存擊穿,緩存擊穿是指緩存中沒有但數據庫中有的數據,并且某一個key非常熱點,在不停的扛著大并發(fā),大并發(fā)集中對這一個點進行訪問,當這個key在失效的瞬間(一般是緩存時間到期),持續(xù)的大并發(fā)就穿破緩存,直接請求數據庫,就像在一個屏障上鑿開了一個洞。

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

2、解決方案

(1)布隆過濾器

布隆過濾器是一個bit向量或者bit,如果我們要映射一個值到布隆過濾器中,我們使用多個不同的哈希函數生成多個哈希值,并將每個生成的哈希值指向的bit位設置為1,如下baidu一詞設置了三個位置為1。

原理:對一個key進行k個hash算法獲取k個值,在比特數組中將這k個值散列后設定為1,然后查的時候如果特定的這幾個位置都為1,那么布隆過濾器判斷該key存在。

怎么解讀Redis緩存穿透、緩存擊穿和緩存雪崩

“tencent”一詞,對應的情況
怎么解讀Redis緩存穿透、緩存擊穿和緩存雪崩
可以看到,不同的詞對應的bit位置可能相同,當詞很多的情況時,可能大部分bit位置都是1,這時查詢taobao可能對應的位置都為1,只能說明taobao一詞可能存在,不是一定存在的,這時1就被覆蓋了,這就是布隆過濾器的誤判。如果它說不存在那肯定不存在,如果它說存在,那數據有可能實際不存在。

Redis的bitmap只支持2^32大小,對應到內存也就是512MB,誤判率萬分之一,可以放下2億左右的數據,性能高,空間占用率及小,省去了大量無效的數據庫連接。

因此我們可以通過布隆過濾器,將Redis緩存穿透控制在一個可容范圍內。

怎么解讀Redis緩存穿透、緩存擊穿和緩存雪崩

使用布隆過濾器:
導入依賴

<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>19.0</version>
</dependency>

代碼:

public class Test {

   private static int size = 1000000;//預計要插入多少數據

   private static double fpp = 0.01;//期望的誤判率

   private static BloomFilter<Integer> bloomFilter = BloomFilter.create(Funnels.integerFunnel(), size, fpp);

   public static void main(String[] args) {
       //插入數據
       for (int i = 0; i < 1000000; i++) {
           bloomFilter.put(i);
       }
       int count = 0;
       for (int i = 1000000; i < 2000000; i++) {
           if (bloomFilter.mightContain(i)) {
               count++;
               System.out.println(i + "誤判了");
           }
       }
       System.out.println("總共的誤判數:" + count);
   }
}

應用:

@Cacheable(value="key1")
public String get(String key) {
   String value = redis.get(key);  
   // redis中不存在該緩存
   if (value  == null) {
   //布隆過濾器也沒有,直接返回
       if(!bloomfilter.mightContain(key)){
           return null;
       }else{
           //布隆過濾器中能查到,不代表一定有,查出來放入redis,同樣也可以避免緩存穿透
           value = db.get(key);
           redis.set(key, value);
       }    
   }
   return value;
}

(2)、緩存空對象
當存儲層不命中后,即使返回的空對象也將其緩存起來,同時會設置一個過期時間,之后再訪問這個數據將會從緩存中獲取,保護了后端數據源。
怎么解讀Redis緩存穿透、緩存擊穿和緩存雪崩
但是這種方法會存在兩個問題:

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

?● 即使對空值設置了過期時間,還是會存在緩存層和存儲層的數據會有一段時間窗口的不一致,這對于需要保持一致性的業(yè)務會有影響。

二、緩存雪崩

(1)、概念
緩存雪崩是指緩存中大批量數據到過期時間,而查詢數據量巨大,引起數據庫壓力過大甚至down機。和緩存擊穿不同的是,緩存擊穿指并發(fā)查同一條數據,緩存雪崩是不同數據都過期了,很多數據都查不到從而查數據庫。
怎么解讀Redis緩存穿透、緩存擊穿和緩存雪崩
產生雪崩的原因之一,假如馬上就要到雙十一零點,很快就會迎來一波搶購,這波商品時間比較集中的放入了緩存,假設緩存一個小時。那么到了凌晨一點鐘的時候,這批商品的緩存就都過期了。而對這批商品的訪問查詢,都落到了數據庫上,對于數據庫而言,就會產生周期性的壓力波峰。

博主在做電商項目的時候,一般有三種方法:
(1)采取不同分類商品,緩存不同周期。在同一分類中的商品,加上一個隨機因子。這樣能盡可能分散緩存過期時間,而且,熱門類目的商品緩存時間長一些,冷門類目的商品緩存時間短一些,也能節(jié)省緩存服務的資源。
(2)如果緩存數據庫是分布式部署,將 熱點數據均勻分布在不同的緩存數據庫中。
(3)設置熱點數據永遠不過期。
怎么解讀Redis緩存穿透、緩存擊穿和緩存雪崩
(4) 使用加鎖限流的方式
怎么解讀Redis緩存穿透、緩存擊穿和緩存雪崩
怎么解讀Redis緩存穿透、緩存擊穿和緩存雪崩
怎么解讀Redis緩存穿透、緩存擊穿和緩存雪崩

三、緩存擊穿

(1)概念
緩存擊穿,是指緩存中沒有但數據庫中有的數據,并且某一個key非常熱點,在不停的扛著大并發(fā),大并發(fā)集中對這一個點進行訪問,當這個key在失效的瞬間(一般是緩存時間到期),持續(xù)的大并發(fā)就穿破緩存,直接請求數據庫,就像在一個屏障上鑿開了一個洞。

(2)解決方案

?● 設置熱點數據永遠不過期。

?● 使用互斥鎖(mutex key)
??業(yè)界比較常用的做法,是使用mutex。簡單地來說,就是在緩存失效的時候(判斷拿出來的值為空),不是立即去load db,而是先使用緩存工具的某些帶成功操作返回值的操作(比如Redis的SETNX或者Memcache的ADD)去set一個mutex key,當操作返回成功時,再進行l(wèi)oad db的操作并回設緩存;否則,就重試整個get緩存的方法。

SETNX,是「SET if Not eXists」的縮寫,也就是只有不存在的時候才設置,可以利用它來實現鎖的效果。

public String get(key) {
     String value = redis.get(key);
     if (value == null) { //代表緩存值過期
         //設置3min的超時,防止del操作失敗的時候,下次緩存過期一直不能load db
      if (redis.setnx(key_mutex, 1, 3 * 60) == 1) {  //代表設置成功
              value = db.get(key);
              redis.set(key, value, expire_secs);
              redis.del(key_mutex);
         } else {  //這個時候代表同時候的其他線程已經load db并回設到緩存了,這時候重試獲取緩存值即可
              sleep(50);
              get(key);  //重試
             }
     } else {
         return value;      
  }
}

看完上述內容是否對您有幫助呢?如果還想對相關知識有進一步的了解或閱讀更多相關文章,請關注億速云行業(yè)資訊頻道,感謝您對億速云的支持。

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI