内射老阿姨1区2区3区4区_久久精品人人做人人爽电影蜜月_久久国产精品亚洲77777_99精品又大又爽又粗少妇毛片

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

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

網(wǎng)站建設(shè)哪家好,找創(chuàng)新互聯(lián)公司!專注于網(wǎng)頁設(shè)計(jì)、網(wǎng)站建設(shè)、微信開發(fā)、小程序開發(fā)、集團(tuán)企業(yè)網(wǎng)站建設(shè)等服務(wù)項(xiàng)目。為回饋新老客戶創(chuàng)新互聯(lián)還提供了棗莊免費(fèi)建站歡迎大家使用!

一、緩存穿透

1、概念

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

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

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

2、解決方案

(1)布隆過濾器

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

原理:對一個(gè)key進(jìn)行k個(gè)hash算法獲取k個(gè)值,在比特?cái)?shù)組中將這k個(gè)值散列后設(shè)定為1,然后查的時(shí)候如果特定的這幾個(gè)位置都為1,那么布隆過濾器判斷該key存在。

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

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

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

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

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

使用布隆過濾器:
導(dǎo)入依賴

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

代碼:

public class Test {

   private static int size = 1000000;//預(yù)計(jì)要插入多少數(shù)據(jù)

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

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

   public static void main(String[] args) {
       //插入數(shù)據(jù)
       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("總共的誤判數(shù):" + count);
   }
}

應(yīng)用:

@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)、緩存空對象
當(dāng)存儲(chǔ)層不命中后,即使返回的空對象也將其緩存起來,同時(shí)會(huì)設(shè)置一個(gè)過期時(shí)間,之后再訪問這個(gè)數(shù)據(jù)將會(huì)從緩存中獲取,保護(hù)了后端數(shù)據(jù)源。
怎么解讀Redis緩存穿透、緩存擊穿和緩存雪崩
但是這種方法會(huì)存在兩個(gè)問題:

?● 如果空值能夠被緩存起來,這就意味著緩存需要更多的空間存儲(chǔ)更多的鍵,因?yàn)檫@當(dāng)中可能會(huì)有很多的空值的鍵;

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

二、緩存雪崩

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

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

三、緩存擊穿

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

(2)解決方案

?● 設(shè)置熱點(diǎn)數(shù)據(jù)永遠(yuǎn)不過期。

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

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

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

看完上述內(nèi)容是否對您有幫助呢?如果還想對相關(guān)知識(shí)有進(jìn)一步的了解或閱讀更多相關(guān)文章,請關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝您對創(chuàng)新互聯(lián)的支持。

文章題目:怎么解讀Redis緩存穿透、緩存擊穿和緩存雪崩
文章轉(zhuǎn)載:http://www.rwnh.cn/article12/jjscgc.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供動(dòng)態(tài)網(wǎng)站網(wǎng)站內(nèi)鏈、網(wǎng)站建設(shè)外貿(mào)網(wǎng)站建設(shè)、微信小程序、移動(dòng)網(wǎng)站建設(shè)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

外貿(mào)網(wǎng)站制作
项城市| 堆龙德庆县| 巧家县| 万荣县| 固始县| 朝阳区| 巴彦县| 定襄县| 青神县| 施秉县| 宁晋县| 华池县| 阳城县| 漳州市| 丹棱县| 赤壁市| 青浦区| 石泉县| 台安县| 宜城市| 册亨县| 钟山县| 江津市| 崇义县| 汕尾市| 漳州市| 西华县| 拉孜县| 吉水县| 阳原县| 葵青区| 前郭尔| 贵溪市| 营口市| 禹城市| 彭阳县| 南城县| 西贡区| 庆元县| 郸城县| 郯城县|