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

redis工具類(緩存的設(shè)置,緩存擊穿,穿透)

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

#maven依賴
		<!--hutool-->
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.8.12</version>
        </dependency>
import cn.hutool.core.date.DateTime;
import cn.hutool.core.util.BooleanUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.hmdp.entity.Shop;
import com.sun.org.apache.bcel.internal.generic.NEW;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;

@Slf4j
@Component
/**
 * 用于解決緩存擊穿和緩存穿透的工具類
 */
public class CacheClient {
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    /**
     * 添加數(shù)據(jù)到redis
     *
     * @param key   名稱
     * @param value 內(nèi)容
     * @param time  有效時(shí)間
     * @param unit  時(shí)間單位
     */
    public void set(String key, Object value, Long time, TimeUnit unit) {
        stringRedisTemplate.opsForValue().set(key, JSONUtil.toJsonStr(value), time, unit);
    }

    /**
     * 設(shè)置邏輯過(guò)期添加數(shù)據(jù)到redis
     *
     * @param key   名稱
     * @param value 內(nèi)容
     * @param time  超時(shí)時(shí)間
     * @param unit  超時(shí)時(shí)間單位
     */
    public void setWithLogicalExpire(String key, Object value, Long time, TimeUnit unit) {
        //設(shè)置邏輯過(guò)期時(shí)間
        RedisData redisData = new RedisData();
        redisData.setData(value);
        redisData.setExpireTime(LocalDateTime.now().plusSeconds(unit.toSeconds(time)));
        //寫(xiě)入redis
        stringRedisTemplate.opsForValue().set(key, JSONUtil.toJsonStr(redisData));
    }

    /**
     * 緩存穿透
     * @param keyPrefix key的前綴
     * @param id id
     * @param type 返回類型
     * @param dbFallback 數(shù)據(jù)庫(kù)查詢
     * @param time 時(shí)間
     * @param unit 時(shí)間單位
     * @param <R> 返回值
     * @param <ID> ID
     * @return
     */
    public <R, ID> R queryWithPassThrough(String keyPrefix, ID id, Class<R> type, Function<ID, R> dbFallback, Long time, TimeUnit unit) {
        String key = keyPrefix + id;
        //1.從redis查詢商品緩存
        String json = stringRedisTemplate.opsForValue().get(key);
        //2.判斷是否存在
        if (StrUtil.isNotBlank(json)) {
            //3。存在直接返回
            R content = JSONUtil.toBean(json, type);
            return content;
        }
        //判斷是否是空值(上面已經(jīng)判斷了數(shù)據(jù)存在的情況,所以這里直接使用!=null就能查出空值)
        if (json != null) {
            return null;
        }
        //4.不存在,查詢數(shù)據(jù)庫(kù)
        R r = dbFallback.apply(id);
        //5.數(shù)據(jù)庫(kù)不存在返回錯(cuò)誤
        if (r == null) {
            //為了防止緩存穿透,將空值寫(xiě)入redis
            stringRedisTemplate.opsForValue().set(key, "", RedisConstants.CACHE_NULL_TTL, TimeUnit.MINUTES);
            //返回
            return null;
        }
        //6。存在寫(xiě)入redis
        stringRedisTemplate.opsForValue().set(key, JSONUtil.toJsonStr(r), time, unit);
        //7.返回
        return r;
    }

    /**
     * 緩存擊穿
     */
    private static final ExecutorService CACHE_THREAD_POOL = Executors.newFixedThreadPool(10);

    public <R,ID> R queryWithLogicExpiredTime(String keyPrefix, ID id, Class<R> type, Function<ID, R> dbFallback, Long time, TimeUnit unit) {
        String key = keyPrefix + id;
        //1.從redis查詢商品緩存
        String json = stringRedisTemplate.opsForValue().get(key);
        //2.判斷是否命中(未命中返回)
        if (StrUtil.isBlank(json)) {
            return null;
        }
        //2.1命中-判斷是否過(guò)期
        RedisData redisData = JSONUtil.toBean(json, RedisData.class);
        R r = JSONUtil.toBean((JSONObject) redisData.getData(), type);
        LocalDateTime expireTime = redisData.getExpireTime();
        if (expireTime.isAfter(LocalDateTime.now())) {
            //未過(guò)期
            return r;
        }
        String lockKey = RedisConstants.LOCK_SHOP_KEY + id;
        try {
            //2.2過(guò)期-獲取互斥鎖
            boolean isLock = tryLock(lockKey);
            //3.判斷鎖是否拿到
            if (isLock) {
                //4.是-開(kāi)啟獨(dú)立線程
                CACHE_THREAD_POOL.submit(() -> {
                    //重建緩存2步走,先查數(shù)據(jù)庫(kù),再寫(xiě)redis
                    //查詢數(shù)據(jù)庫(kù)
                    R r1 = dbFallback.apply(id);
                    //寫(xiě)入redis
                    this.setWithLogicalExpire(key,r1,time,unit);
                });
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            //4.2釋放鎖
            delLock(lockKey);
        }
        //5.返回?cái)?shù)據(jù)
        return r;
    }

    //利用redis中的setnx來(lái)設(shè)置鎖
    private boolean tryLock(String key) {
        Boolean flag = stringRedisTemplate.opsForValue().setIfAbsent(key, "1", 10L, TimeUnit.SECONDS);
        //自動(dòng)拆箱有可能返回空值,所以用工具類
        return BooleanUtil.isTrue(flag);
    }

    //刪除鎖
    private void delLock(String key) {
        stringRedisTemplate.delete(key);
    }
}

文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-615027.html

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

本文來(lái)自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(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 原理緩存過(guò)期、一致性hash、雪崩、穿透、并發(fā)、布隆、緩存更新策略、緩存數(shù)據(jù)庫(kù)一致性

    Redis 原理緩存過(guò)期、一致性hash、雪崩、穿透、并發(fā)、布隆、緩存更新策略、緩存數(shù)據(jù)庫(kù)一致性

    redis的過(guò)期策略可以通過(guò)配置文件進(jìn)行配置 redis會(huì)把設(shè)置了過(guò)期時(shí)間的key放在單獨(dú)的字典中,定時(shí)遍歷來(lái)刪除到期的key。 1).每100ms從過(guò)期字典中 隨機(jī)挑選20個(gè),把其中過(guò)期的key刪除; 2).如果過(guò)期的key占比超過(guò)1/4,重復(fù)步驟1 為了保證不會(huì)循環(huán)過(guò)度,導(dǎo)致卡頓,掃描時(shí)間上限

    2024年02月08日
    瀏覽(31)
  • 緩存面試解析:穿透、擊穿、雪崩,一致性、分布式鎖、Redis過(guò)期,海量數(shù)據(jù)查找

    緩存面試解析:穿透、擊穿、雪崩,一致性、分布式鎖、Redis過(guò)期,海量數(shù)據(jù)查找

    在程序內(nèi)部使用緩存,比如使用map等數(shù)據(jù)結(jié)構(gòu)作為內(nèi)部緩存,可以快速獲取對(duì)象。通過(guò)將經(jīng)常使用的數(shù)據(jù)存儲(chǔ)在緩存中,可以減少對(duì)數(shù)據(jù)庫(kù)的頻繁訪問(wèn),從而提高系統(tǒng)的響應(yīng)速度和性能。緩存可以將數(shù)據(jù)保存在內(nèi)存中,讀取速度更快,能夠大大縮短數(shù)據(jù)訪問(wèn)的時(shí)間,提升用戶

    2024年02月14日
    瀏覽(37)
  • Redis 緩存穿透、緩存雪崩、緩存擊穿

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

    緩存穿透是指客戶端請(qǐng)求的數(shù)據(jù)在緩存中和數(shù)據(jù)庫(kù)中都不存在,這樣緩存永遠(yuǎn)不會(huì)生效,這些請(qǐng)求都會(huì)打到數(shù)據(jù)庫(kù)。 常見(jiàn)的解決方案有兩種: ????????緩存空對(duì)象 ???????? ????????優(yōu)點(diǎn):實(shí)現(xiàn)簡(jiǎn)單,維護(hù)方便 ????????????????缺點(diǎn): 額外的內(nèi)存消耗 可能造

    2024年02月02日
    瀏覽(28)
  • redis 緩存雪崩 && 緩存擊穿 && 緩存穿透

    什么是緩存雪崩 當(dāng)我們提到緩存系統(tǒng)中的問(wèn)題,緩存雪崩是一個(gè)經(jīng)常被討論的話題。緩存雪崩是指在某一時(shí)刻發(fā)生大量的緩存失效,導(dǎo)致瞬間大量的請(qǐng)求直接打到了數(shù)據(jù)庫(kù),可能會(huì)導(dǎo)致數(shù)據(jù)庫(kù)瞬間壓力過(guò)大甚至宕機(jī)。尤其在高并發(fā)的系統(tǒng)中,這種情況會(huì)導(dǎo)致連鎖反應(yīng),整個(gè)系

    2024年02月07日
    瀏覽(30)
  • Redis-緩存穿透、緩存崩潰、緩存擊穿

    本文主要介紹Redis中緩存穿透、緩存崩潰和緩存擊穿 一般情況下,用戶請(qǐng)求到后臺(tái),會(huì)先從緩存中取數(shù)據(jù)。如果在緩存中取到數(shù)據(jù),就直接返回 結(jié)果;如果取不到數(shù)據(jù)就需要查詢數(shù)據(jù)庫(kù),從數(shù)據(jù)庫(kù)中取到數(shù)據(jù)后會(huì)同步更新到緩存,并返回結(jié)果。下一個(gè)用戶就可以直接從緩存中

    2024年02月16日
    瀏覽(19)
  • Redis之緩存穿透+緩存雪崩+緩存擊穿

    Redis之緩存穿透+緩存雪崩+緩存擊穿

    在生產(chǎn)環(huán)境中,會(huì)因?yàn)楹芏嗟脑蛟斐稍L問(wèn)請(qǐng)求繞過(guò)了緩存,都需要訪問(wèn)數(shù)據(jù)庫(kù)持久層,雖然對(duì)Redsi緩存服務(wù)器不會(huì)造成影響,但是數(shù)據(jù)庫(kù)的負(fù)載就會(huì)增大,使緩存的作用降低 ??緩存穿透是指查詢一個(gè)根本不存在的數(shù)據(jù),緩存層和持久層都不會(huì)命中。在日常工作中出于容錯(cuò)

    2023年04月09日
    瀏覽(24)
  • Redis的緩存穿透,緩存擊穿,緩存雪崩

    Redis的緩存穿透,緩存擊穿,緩存雪崩

    什么是緩存穿透? 緩存穿透說(shuō)簡(jiǎn)單點(diǎn)就是大量請(qǐng)求的 key 是不合理的, 根本不存在于緩存中,也不存在于數(shù)據(jù)庫(kù)中 。這就導(dǎo)致這些請(qǐng)求直接到了數(shù)據(jù)庫(kù)上,根本沒(méi)有經(jīng)過(guò)緩存這一層,對(duì)數(shù)據(jù)庫(kù)造成了巨大的壓力,可能直接就被這么多請(qǐng)求弄宕機(jī)了。 eg:某個(gè)黑客故意制造一

    2024年02月10日
    瀏覽(20)
  • 68、Redis:緩存雪崩、緩存穿透、緩存擊穿

    緩存雪崩是指緩存同一時(shí)間大面積的失效,所以,后面的請(qǐng)求都會(huì)落到數(shù)據(jù)庫(kù)上,造成數(shù)據(jù)庫(kù)短時(shí)間內(nèi)承受大量請(qǐng)求而崩掉。 緩存數(shù)據(jù)的過(guò)期時(shí)間設(shè)置隨機(jī),防止同一時(shí)間大量數(shù)據(jù)過(guò)期現(xiàn)象發(fā)生 給每一個(gè)緩存數(shù)據(jù)增加相應(yīng)的緩存標(biāo)記,記錄緩存是否失效,如果緩存標(biāo)記失效

    2024年02月16日
    瀏覽(22)
  • Redis 緩存預(yù)熱+緩存雪崩+緩存擊穿+緩存穿透

    Redis 緩存預(yù)熱+緩存雪崩+緩存擊穿+緩存穿透

    面試題: 緩存預(yù)熱、雪萌、穿透、擊穿分別是什么?你遇到過(guò)那幾個(gè)情況? 緩存預(yù)熱你是怎么做的? 如何造免或者減少緩存雪崩? 穿透和擊穿有什么區(qū)別?他兩是一個(gè)意思還是載然不同? 穿適和擊穿你有什么解決方案?如何避免? 假如出現(xiàn)了緩存不一致,你有哪些修補(bǔ)方

    2024年02月10日
    瀏覽(20)
  • Redis緩存預(yù)熱-緩存穿透-緩存雪崩-緩存擊穿

    Redis緩存預(yù)熱-緩存穿透-緩存雪崩-緩存擊穿

    什么叫緩存穿透? 模擬一個(gè)場(chǎng)景: 前端用戶發(fā)送請(qǐng)求獲取數(shù)據(jù),后端首先會(huì)在緩存Redis中查詢,如果能查到數(shù)據(jù),則直接返回.如果緩存中查不到數(shù)據(jù),則要去數(shù)據(jù)庫(kù)查詢,如果數(shù)據(jù)庫(kù)有,將數(shù)據(jù)保存到Redis緩存中并且返回用戶數(shù)據(jù).如果數(shù)據(jù)庫(kù)沒(méi)有則返回null; 這個(gè)緩存穿透的問(wèn)題就是這個(gè)

    2024年03月09日
    瀏覽(29)

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

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

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

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包