国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

緩存穿透、緩存雪崩、緩存擊穿解決方案

這篇具有很好參考價(jià)值的文章主要介紹了緩存穿透、緩存雪崩、緩存擊穿解決方案。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

什么是緩存

緩存就是數(shù)據(jù)交換的緩沖區(qū)(稱作Cache),是存貯數(shù)據(jù)的臨時(shí)地方,一般讀寫性能較高。

緩存穿透、緩存雪崩、緩存擊穿解決方案

緩存穿透、緩存雪崩、緩存擊穿解決方案

添加 redis 緩存

緩存穿透、緩存雪崩、緩存擊穿解決方案

給店鋪類型查詢業(yè)務(wù)添加緩存

緩存穿透、緩存雪崩、緩存擊穿解決方案

需求:添加ShopTypeController中的queryTypeList方法,添加查詢緩存

緩存更新策略

緩存穿透、緩存雪崩、緩存擊穿解決方案

業(yè)務(wù)場景:

低一致性需求:使用內(nèi)存淘汰機(jī)制。例如店鋪類型的查詢緩存

高一致性需求:主動(dòng)更新,并以超時(shí)剔除作為兜底方案。例如店鋪詳情查詢的緩存

緩存穿透、緩存雪崩、緩存擊穿解決方案

操作緩存和數(shù)據(jù)庫時(shí)有三個(gè)問題需要考慮:

1.刪除緩存還是更新緩存

  • 更新緩存:每次更新數(shù)據(jù)庫都更新緩存,無效寫操作較多(×)

  • 刪除緩存:更新數(shù)據(jù)庫時(shí)讓緩存失效,查詢時(shí)再更新緩存(?)

2.如何保證緩存與數(shù)據(jù)庫的操作同時(shí)成功或失敗

  • 單體系統(tǒng):將緩存與數(shù)據(jù)庫操作放在一個(gè)事務(wù)

  • 分布式系統(tǒng):利用TCC等分布式事務(wù)方案

3.先操作緩存還是先操作數(shù)據(jù)庫

  • 先刪除緩存,在操作數(shù)據(jù)庫

  • 先操作數(shù)據(jù)庫,再刪除緩存

緩存穿透、緩存雪崩、緩存擊穿解決方案

緩存穿透、緩存雪崩、緩存擊穿解決方案

讀操作:

  • 緩存命中則直接返回

  • 緩存未命中則查詢數(shù)據(jù)庫,并寫入緩存,設(shè)定超時(shí)時(shí)間

寫操作:

  • 先寫數(shù)據(jù)庫,然后再刪除緩存

  • 要確保數(shù)據(jù)庫與緩存操作的原子性

給查詢商鋪的緩存添加超時(shí)剔除和主動(dòng)更新的策略

修改ShopController的業(yè)務(wù)邏輯,滿足下面的需求

① 根據(jù)id查詢商鋪時(shí),如果緩存未命中,則查詢數(shù)據(jù)庫,將數(shù)據(jù)庫數(shù)據(jù)寫入緩存,并設(shè)置超時(shí)時(shí)間

 //6.存在,將商鋪數(shù)據(jù)寫入redis
 stringRedisTemplate.opsForValue().set(key, JSONUtil.toJsonStr(shop), CACHE_SHOP_TTL, TimeUnit.MINUTES);

② 根據(jù)id修改店鋪時(shí),先修改數(shù)據(jù)庫,再修改緩存

 @Override
    @Transactional
    public Result update(Shop shop) {
        Long id = shop.getId();
        if (id==null) {
            return Result.fail("店鋪id不為空");
        }
        //1更新數(shù)據(jù)庫
        updateById(shop);
        //2.刪除緩存
        stringRedisTemplate.delete(CACHE_SHOP_KEY + id);
        return Result.ok();
    }

緩存穿透

緩存穿透是指客戶端請(qǐng)求的數(shù)據(jù)在緩存中和數(shù)據(jù)庫中都不存在,這樣緩存永遠(yuǎn)不會(huì)生效,這些請(qǐng)求都會(huì)打到數(shù)據(jù)庫

常見的解決方案有兩種:

緩存穿透、緩存雪崩、緩存擊穿解決方案

1.緩存空對(duì)象

優(yōu)點(diǎn):實(shí)現(xiàn)簡單,維護(hù)方便

缺點(diǎn):額外的內(nèi)存消耗,可能造成短期的數(shù)據(jù)不一致

2.布隆過濾

優(yōu)點(diǎn):內(nèi)存占用少,沒有多余的key

缺點(diǎn):實(shí)現(xiàn)復(fù)雜,存在誤判

緩存穿透、緩存雪崩、緩存擊穿解決方案

其他的解決方案

1.增加id的復(fù)雜度,避免被猜測id規(guī)律

2.做好數(shù)據(jù)的基礎(chǔ)格式校驗(yàn)

3.加強(qiáng)用戶權(quán)限校驗(yàn)

4.做好熱點(diǎn)參數(shù)的限流

緩存雪崩

緩存雪崩是指在同一時(shí)段大量的緩存key同時(shí)失效或者Redis服務(wù)宕機(jī),導(dǎo)致大量請(qǐng)求到達(dá)數(shù)據(jù)庫,帶來巨大壓力

緩存穿透、緩存雪崩、緩存擊穿解決方案

解決方案:

1.給不同的key的TTL添加隨機(jī)值

2.利用redis集群提高服務(wù)的可用性

3.給緩存業(yè)務(wù)添加降級(jí)限流策略

4.給業(yè)務(wù)添加多級(jí)緩存

緩存擊穿

緩存擊穿問題也叫熱點(diǎn)key問題,就是一個(gè)被高并發(fā)訪問并且緩存重建業(yè)務(wù)較復(fù)雜的
key突然失效了,無數(shù)的請(qǐng)求訪問會(huì)在瞬間給數(shù)據(jù)庫帶來巨大的沖擊

緩存穿透、緩存雪崩、緩存擊穿解決方案

常見的解決方案有兩種:

1.互斥鎖

2.邏輯過期

緩存穿透、緩存雪崩、緩存擊穿解決方案

優(yōu)缺點(diǎn):

緩存穿透、緩存雪崩、緩存擊穿解決方案

基于互斥鎖方式解決緩存擊穿問題

需求:修改根據(jù)id查詢商鋪的業(yè)務(wù),基于互斥鎖來解決緩存擊穿問題

緩存穿透、緩存雪崩、緩存擊穿解決方案

基于邏輯過期解決緩存擊穿問題

需求:修改根據(jù)id查詢商鋪的業(yè)務(wù),基于邏輯過期方式來解決緩存擊穿問題

緩存穿透、緩存雪崩、緩存擊穿解決方案

緩存工具封裝

基于StringRedisTemplate封裝一個(gè)緩存工具類,滿足下列需求:

方法:

1.將任意Java對(duì)象序列化為json并存儲(chǔ)在String類型的key中,并且設(shè)置TTL過期時(shí)間

2.將任意Java對(duì)象序列化為json并存儲(chǔ)在String類型的key中,并且設(shè)置邏輯過期時(shí)間,用于處理緩存擊穿問題

3.根據(jù)指定的key查詢緩存,并反序列化為指定類型,利用緩存空值的方式解決緩存穿透問題

4.根據(jù)指定的key查詢緩存,并反序列化為指定類型,需要利用邏輯過期解決緩存擊穿問題

CacheClient

@Slf4j
@Component
public class CacheClient {

    private final StringRedisTemplate stringRedisTemplate;

    private static final ExecutorService CACHE_REBUILD_EXECUTOR = Executors.newFixedThreadPool(10);

    public CacheClient(StringRedisTemplate stringRedisTemplate) {
        this.stringRedisTemplate = stringRedisTemplate;
    }

    public void set(String key, Object value, Long time, TimeUnit unit) {
        stringRedisTemplate.opsForValue().set(key, JSONUtil.toJsonStr(value), time, unit);
    }

    public void setWithLogicExpire(String key, Object value, Long time, TimeUnit unit) {
        //設(shè)置邏輯過期
        RedisData redisData = new RedisData();
        redisData.setData(value);
        redisData.setExpireTime(LocalDateTime.now().plusSeconds(unit.toSeconds(time)));
        //寫入redis
        stringRedisTemplate.opsForValue().set(key, JSONUtil.toJsonStr(value), time, unit);
    }

    //解決緩存穿透
    public <R, ID> R queryWithPassThrough(
            String kerPrefix, ID id, Class<R> type, Function<ID, R> dbFallback, Long time, TimeUnit unit) {
        //1.查詢商鋪緩存
        String key = kerPrefix + id;
        String json = stringRedisTemplate.opsForValue().get(key);

        //2.判斷是否存在
        if (StrUtil.isNotBlank(json)) {
            //3.緩存存在,返回

            return JSONUtil.toBean(json, type);
        }
        //判斷命中的是否是空值
        if (json != null) {
            //返回一個(gè)錯(cuò)誤的信息
            return null;
        }

        //4.不存在,根據(jù)id查詢數(shù)據(jù)庫
        R r = dbFallback.apply(id);
        //5.不存在,返回錯(cuò)誤
        if (r == null) {
            //將空值寫入數(shù)據(jù)庫
            stringRedisTemplate.opsForValue().set(key, "", CACHE_NULL_TTL, TimeUnit.MINUTES);

            return null;
        }
        //6.存在,將商鋪數(shù)據(jù)寫入redis
        this.set(key, r, time, unit);
        //7.返回
        return r;
    }

    //解決緩存擊穿
    public <R, ID> R queryWithLogicExpire(
            String keyPrefix, ID id, Class<R> type, Function<ID, R> dbFallBack, Long time, TimeUnit unit) {
        //1.查詢商鋪緩存
        String key = keyPrefix + id;
        String json = stringRedisTemplate.opsForValue().get(key);

        //2.判斷是否存在
        if (StrUtil.isBlank(json)) {
            //3.緩存存在,返回
            return null;
        }
        //4.命中,需要把json反序列化為對(duì)象
        RedisData redisData = JSONUtil.toBean(json, RedisData.class);
        R r = JSONUtil.toBean((JSONObject) redisData.getData(), type);
        LocalDateTime expireTime = redisData.getExpireTime();

        if (expireTime.isAfter(LocalDateTime.now())) {
            //5.1.未過期,返回商鋪信息
            return r;
        }
        //5.2 已過期,需要緩存重建
        //6.緩存重建
        //6.1.獲取互斥鎖
        String lockKey = LOCK_SHOP_KEY + id;
        boolean isLock = tryLock(lockKey);
        //6.2判斷是否獲取鎖成功
        if (isLock) {
            //6.3成功,開啟獨(dú)立線程,實(shí)現(xiàn)緩存重建
            CACHE_REBUILD_EXECUTOR.submit(() -> {
                try {
                    //查詢數(shù)據(jù)庫
                    R r1 = dbFallBack.apply(id);
                    //寫入redis
                    this.setWithLogicExpire(key, r1, time, unit);

                } catch (Exception e) {
                    throw new RuntimeException(e);
                } finally {
                    //釋放鎖
                    unLock(lockKey);
                }
            });
        }
        //6.4返回過期的商鋪信息
        return r;
    }

    private boolean tryLock(String key) {
        Boolean flag = stringRedisTemplate.opsForValue().setIfAbsent(key, "1", 10L, TimeUnit.MINUTES);
        return BooleanUtil.isTrue(flag);
    }

    private void unLock(String key) {
        stringRedisTemplate.delete(key);
    }
}

ShopServiceImpl

   @Resource
    private CacheClient cacheClient;

    @Override
    public Result queryById(Long id) {
        //緩存穿透
        //Shop shop = cacheClient.queryWithPassThrough(CACHE_SHOP_KEY,id,Shop.class,this::getById,CACHE_SHOP_TTL,TimeUnit.MINUTES);
        //Shop shop = queryWithPassThrough(id);

        //互斥鎖解決緩存擊穿
        //Shop shop = queryWithMutex(id);

        //邏輯過期解決緩存擊穿
        Shop shop = cacheClient.queryWithLogicExpire(CACHE_SHOP_KEY, id, Shop.class, this::getById, 20L, TimeUnit.SECONDS);
        //Shop shop = queryWithLogicExpire(id);
        if (shop == null) {
            return Result.fail("店鋪不存在");
        }
        //7.返回
        return Result.ok(shop);
    }

視頻地址文章來源地址http://www.zghlxwxcb.cn/news/detail-408641.html

到了這里,關(guān)于緩存穿透、緩存雪崩、緩存擊穿解決方案的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • redis中緩存雪崩,緩存穿透,緩存擊穿的原因以及解決方案

    redis中緩存雪崩,緩存穿透,緩存擊穿的原因以及解決方案

    在redis中,新,舊數(shù)據(jù)交替時(shí)候,舊數(shù)據(jù)進(jìn)行了刪除,新數(shù)據(jù)沒有更新過來,造成在高并發(fā)環(huán)境下,大量請(qǐng)求查詢r(jià)edis沒有數(shù)據(jù),直接查詢mysql,造成mysql的壓力驟增,給mysql造成極大的壓力,造成一連串的后續(xù)異常反應(yīng)。 1.大多數(shù)系統(tǒng)設(shè)計(jì)者 考慮用加鎖 (最多的解決方案)或

    2024年02月15日
    瀏覽(36)
  • redis實(shí)戰(zhàn)-緩存三劍客穿透擊穿雪崩解決方案

    redis實(shí)戰(zhàn)-緩存三劍客穿透擊穿雪崩解決方案

    緩存穿透 :緩存穿透是指客戶端請(qǐng)求的 數(shù)據(jù)在緩存中和數(shù)據(jù)庫中都不存在 ,這樣緩存永遠(yuǎn)不會(huì)生效,這些請(qǐng)求都會(huì)打到數(shù)據(jù)庫, 造成數(shù)據(jù)庫壓力 ,也讓緩存沒有發(fā)揮出應(yīng)有的作用 緩存空對(duì)象 當(dāng)我們客戶端訪問不存在的數(shù)據(jù)時(shí),先請(qǐng)求redis,但是此時(shí)redis中沒有數(shù)據(jù),此時(shí)

    2024年02月11日
    瀏覽(29)
  • Redis中的緩存穿透、雪崩、擊穿的原因以及解決方案

    Redis中的緩存穿透、雪崩、擊穿的原因以及解決方案

    是指用戶查詢數(shù)據(jù),在數(shù)據(jù)庫沒有,自然在緩存中也不會(huì)有。這樣就導(dǎo)致用戶查詢的時(shí)候,在緩存中找不到,每次都要去數(shù)據(jù)庫再查詢一遍,然后返回空(相當(dāng)于進(jìn)行了兩次無用的查詢)。這樣請(qǐng)求就繞過緩存直接查數(shù)據(jù)庫,這也是經(jīng)常提的緩存命中率問題。 我們可以簡單的

    2024年02月12日
    瀏覽(21)
  • 【Redis從入門到進(jìn)階】第 6 講:緩存雪崩、擊穿、穿透場景與解決方案

    【Redis從入門到進(jìn)階】第 6 講:緩存雪崩、擊穿、穿透場景與解決方案

    本文已收錄于專欄 ??《Redis從入門到進(jìn)階》?? ?? 本專欄開啟,目的在于幫助大家更好的掌握學(xué)習(xí) Redis ,同時(shí)也是為了記錄我自己學(xué)習(xí) Redis 的過程,將會(huì)從基礎(chǔ)的數(shù)據(jù)類型開始記錄,直到一些更多的應(yīng)用,如緩存擊穿還有分布式鎖以及 Redis 持久化等。希望大家有問題也可

    2023年04月12日
    瀏覽(233)
  • Redis緩存雪崩、穿透、擊穿原因分析和解決方案,附Redis管道使用技巧

    Redis緩存雪崩、穿透、擊穿原因分析和解決方案,附Redis管道使用技巧

    先給大家附上其他幾篇文章,感興趣的自行開車導(dǎo)航 Redis過期策略和持久化機(jī)制全面揭秘,教你如何合理配置 【深入淺出Redis 一】從版本特性到數(shù)據(jù)類型到線程模型,帶你了解Redis的核心特性和應(yīng)用場景! 一次redis OOM問題分析解決,rdbtools安裝分析redis內(nèi)存 Redis管道(pipelin

    2024年02月16日
    瀏覽(23)
  • 探討Redis緩存問題及解決方案:緩存穿透、緩存擊穿、緩存雪崩與緩存預(yù)熱(如何解決Redis緩存中的常見問題并提高應(yīng)用性能)

    探討Redis緩存問題及解決方案:緩存穿透、緩存擊穿、緩存雪崩與緩存預(yù)熱(如何解決Redis緩存中的常見問題并提高應(yīng)用性能)

    Redis是一種非常流行的開源緩存系統(tǒng),用于緩存數(shù)據(jù)以提高應(yīng)用程序性能。但是,如果我們不注意一些緩存問題,Redis也可能會(huì)導(dǎo)致一些性能問題。在本文中,我們將探討Redis中的一些常見緩存問題,并提供解決方案。 緩存穿透指的是當(dāng)一個(gè)請(qǐng)求嘗試訪問一個(gè)不存在于緩存中的

    2024年02月03日
    瀏覽(169)
  • Redis什么是緩存穿透、擊穿、雪崩?如何解決

    Redis什么是緩存穿透、擊穿、雪崩?如何解決

    通常后端會(huì)采用Mysql等磁盤數(shù)據(jù)庫,可以持久化但是訪問慢,高并發(fā)時(shí)性能差,需要設(shè)置Nosql內(nèi)存型數(shù)據(jù)庫緩存:Redis等 但緩存可能出現(xiàn):緩存穿透、緩存擊穿、緩存雪崩等問題 查找數(shù)據(jù)的順序是:先查找緩存,再查找數(shù)據(jù)庫 當(dāng)查找一個(gè)數(shù)據(jù)時(shí),緩存沒有都會(huì)請(qǐng)求數(shù)據(jù)庫,當(dāng)

    2024年02月09日
    瀏覽(30)
  • 什么是reids緩存雪崩、穿透、擊穿

    什么是reids緩存雪崩、穿透、擊穿

    1.Reids 緩存雪崩 Redis緩存key同一時(shí)間大量失效,導(dǎo)致大量請(qǐng)求全部打到數(shù)據(jù)庫,造成數(shù)據(jù)庫掛掉 解決方案 設(shè)置緩存失效時(shí)間,隨機(jī)初始化失效時(shí)間 部署集群的時(shí)候,把熱點(diǎn)數(shù)據(jù)平均分布到不同redis節(jié)點(diǎn)上去 暴力方法,不設(shè)置失效時(shí)間,永遠(yuǎn)不失效 利用定時(shí)任務(wù)刷新緩存時(shí)間

    2024年01月23日
    瀏覽(16)
  • redis的緩存穿透,緩存并發(fā),緩存雪崩,緩存問題及解決方案

    redis的緩存穿透,緩存并發(fā),緩存雪崩,緩存問題及解決方案

    緩存穿透 問題原因 解決方案 緩存并發(fā) 緩存雪崩 緩存失效時(shí)間設(shè)置一致導(dǎo)致的。 解決方案: 1)方案一 2)方案二 如何設(shè)計(jì)一個(gè)緩存策略,緩存熱點(diǎn)數(shù)據(jù)?

    2024年02月21日
    瀏覽(27)
  • 緩存雪崩、緩存擊穿、緩存穿透原因及解決辦法

    緩存雪崩是指在緩存中的大量數(shù)據(jù)在同一個(gè)時(shí)刻全部過期,導(dǎo)致原本這些可以由緩存中間件處理的高并發(fā)請(qǐng)求,一下子全部打到數(shù)據(jù)庫,導(dǎo)致數(shù)據(jù)庫服務(wù)器崩潰的一種現(xiàn)象。那么出現(xiàn)緩存雪崩的原因可以有①:緩存中間件宕機(jī)。②:緩存中大部分key都設(shè)置了相同的時(shí)間,導(dǎo)致

    2024年02月08日
    瀏覽(90)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包