天天看點

什麼是緩存穿透、緩存雪崩 及 解決緩存穿透、雪崩解決方案實作1、 緩存穿透問題的解決思路2、 緩存雪崩問題及解決思路

(目錄)

1、 緩存穿透問題的解決思路

緩存穿透 :

緩存穿透

是 指

用戶端請求的資料在緩存中和資料庫中都不存在

,這樣緩存永遠不會生效,這些請求都會打到資料庫。

常見的解決方案有兩種:

  1. 緩存空對象

優點:
  • 實作簡單,維護友善
缺點:
  • 額外的記憶體消耗
  • 可能造成短期的不一緻
  1. 布隆過濾

優點:
  • 記憶體占用較少,沒有多餘key
缺點:
  • 實作複雜
  • 存在誤判可能
什麼是緩存穿透、緩存雪崩 及 解決緩存穿透、雪崩解決方案實作1、 緩存穿透問題的解決思路2、 緩存雪崩問題及解決思路

緩存空對象思路分析:

當我們用戶端通路不存在的資料時,先請求redis,但是此時redis中沒有資料,此時會通路到資料庫,但是資料庫中也沒有資料,這個資料穿透了緩存,直擊資料庫,我們都知道資料庫能夠承載的并發不如redis這麼高,如果大量的請求同時過來通路這種不存在的資料,這些請求就都會通路到資料庫。

簡單的解決方案就是哪怕這個資料在資料庫中也不存在,我們也把這個資料存入到redis中去,這樣,下次使用者過來通路這個不存在的資料,那麼在redis中也能找到這個資料就不會進入到緩存了

布隆過濾:

布隆過濾器其實采用的是哈希思想來解決這個問題

,通過一個龐大的二進制數組,走哈希思想去判斷目前這個要查詢的這個資料是否存在,如果布隆過濾器判斷存在,則放行,這個請求會去通路redis,哪怕此時redis中的資料過期了,但是資料庫中一定存在這個資料,在資料庫中查詢出來這個資料後,再将其放入到redis中。

假設布隆過濾器判斷這個資料不存在,則直接傳回

這種

方式優點在于節約記憶體空間,存在誤判,誤判原因在于:布隆過濾器走的是哈希思想,隻要哈希思想,就可能存在哈希沖突

什麼是緩存穿透、緩存雪崩 及 解決緩存穿透、雪崩解決方案實作1、 緩存穿透問題的解決思路2、 緩存雪崩問題及解決思路

① 編碼解決商品查詢的緩存穿透問題:

核心思路如下:

  • 在原來的邏輯中:

我們如果發現這個資料在mysql中不存在,直接就傳回404了

,這樣是會

存在緩存穿透問題

  • 現在的邏輯中:
如果這個

資料不存在

,我們不會傳回404 ,還是會

把這個資料寫入到Redis中,并且将value設定為空

當再次發起查詢時

,我們如果發現命中之後,

判斷value

是否是null,如果是null,則是之前寫入的資料,證明是緩存穿透資料,如果不是,則直接傳回資料。
什麼是緩存穿透、緩存雪崩 及 解決緩存穿透、雪崩解決方案實作1、 緩存穿透問題的解決思路2、 緩存雪崩問題及解決思路

代碼:

修改 ShopServiceImpl 中 queryShopById 方法 中的 不存在邏輯
/**
     *  查詢商鋪
     * @param id
     * @return
     */
    @Override
    public Result queryShopById(Long id) {

        // 1. 從 Redis 中查詢商鋪緩存
        String shopJson = stringRedisTemplate.opsForValue().get(CACHE_SHOP_KEY + id);

        // 2. 判斷是否存在
        // 3. 存在 , 直接傳回
        if(StrUtil.isNotBlank(shopJson)){
            Shop shop=JSONUtil.toBean(shopJson, Shop.class);
            return Result.ok(shop);
        }

        //判斷命中空值 傳回 404
        if(shopJson != null) {
            // 傳回一個錯誤資訊
            return Result.fail("商鋪不存在");
        }

        // 4. 不存在 ,根據 id 去資料庫查詢
        Shop shop = getById(id);
        // 5. 不存在 , 傳回 404
        if(shop==null){
            stringRedisTemplate.opsForValue().set(CACHE_SHOP_KEY + id, "",CACHE_NULL_TTL,TimeUnit.MINUTES);
            return Result.fail("商鋪不存在");
        }

        // 6. 存在 , 寫入 Redis
        stringRedisTemplate.opsForValue().set(CACHE_SHOP_KEY + id, JSONUtil.toJsonStr(shop),CACHE_SHOP_TTL, TimeUnit.MINUTES);

        return Result.ok(shop);
    }
           
什麼是緩存穿透、緩存雪崩 及 解決緩存穿透、雪崩解決方案實作1、 緩存穿透問題的解決思路2、 緩存雪崩問題及解決思路

② 總結:

  1. 緩存穿透産生的原因是什麼?

使用者請求的資料在緩存中和資料庫中都不存在

,不斷發起這樣的請求,給資料庫帶來巨大壓力
  1. 緩存穿透的解決方案有哪些

  • 緩存null值

  • 布隆過濾

  • 增強id的複雜度

    ,避免被猜測id規律
  • 做好資料的

    基礎格式校驗

  • 加強

    使用者權限校驗

  • 做好

    熱點參數的限流

2、 緩存雪崩問題及解決思路

緩存雪崩:

  1. 給不同的Key的

    TTL添加随機值

  2. 利用

    Redis叢集

    提高服務的可用性
  3. 給緩存業務添加

    降級限流政策

  4. 給業務添加

    多級緩存