最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

在SpringBoot中如何利用Redis實現(xiàn)互斥鎖

 更新時間:2023年09月27日 11:25:00   作者:IDIOT___IDIOT  
當(dāng)我們利用Redis存儲熱點數(shù)據(jù)時,突然就過期失效或者被刪除了,導(dǎo)致大量請求同時訪問數(shù)據(jù)庫,增加了數(shù)據(jù)庫的負(fù)載,為減輕數(shù)據(jù)庫的負(fù)載我們利用互斥鎖,本文重點介紹在SpringBoot中如何利用Redis實現(xiàn)互斥鎖,感興趣的朋友一起看看吧

在SpringBoot中利用Redis實現(xiàn)互斥鎖

基本知識

前提條件,有一個能夠在Springboot中使用Redis的項目,或者能夠直接開也行

為什么要實現(xiàn)互斥鎖:當(dāng)我們利用Redis存儲熱點數(shù)據(jù)時,突然就過期失效或者被刪除了,導(dǎo)致大量請求同時訪問數(shù)據(jù)庫,增加了數(shù)據(jù)庫的負(fù)載。為減輕數(shù)據(jù)庫的負(fù)載我們利用互斥鎖。

業(yè)務(wù)的一個邏輯圖流程:

在這里插入圖片描述

核心思路:相較于原來從緩存中查詢不到數(shù)據(jù)后直接查詢數(shù)據(jù)庫而言,現(xiàn)在的方案是 進(jìn)行查詢之后,如果從緩存沒有查詢到數(shù)據(jù),則進(jìn)行互斥鎖的獲取,獲取互斥鎖后,判斷是否獲得到了鎖,如果沒有獲得到,則休眠,過一會再進(jìn)行嘗試,直到獲取到鎖為止(這個嘗試,要重新從Redis再次嘗試獲取數(shù)據(jù),可能別的鎖已經(jīng)獲取到了),才能進(jìn)行查詢

如果獲取到了鎖的線程,再去進(jìn)行查詢,查詢后將數(shù)據(jù)寫入redis,再釋放鎖,返回數(shù)據(jù),利用互斥鎖就能保證只有一個線程去執(zhí)行操作數(shù)據(jù)庫的邏輯,防止緩存擊穿

操作鎖的核心思路就是利用redis的setnx方法來表示獲取鎖,該方法含義是redis中如果沒有這個key,則插入成功,返回1

具體實現(xiàn)

設(shè)置鎖,刪除鎖

   /**
     * 根據(jù)name對特定的數(shù)據(jù)進(jìn)行鎖
     * @param name
     * @return
     */
public boolean setLock(String name) {
    return Boolean.TRUE.equals(redisTemplate.opsForValue().setIfAbsent(name, true, 10, TimeUnit.SECONDS));
}
public boolean releaseLock(String name) {
    return Boolean.TRUE.equals(redisTemplate.delete(name));
}

具體流程實現(xiàn)

@GetMapping("/getOneByLock/{sequence}")
public BaseResponse<Sentences> getOneByLock(@PathVariable long sequence) {
    // 從redis中查信息
    String name = "test:redis:sentences:"+ sequence;
    Sentences sentence = (Sentences) redisTemplate.opsForValue().get(name);
    // 命中返回數(shù)據(jù)
    if(sentence != null ){
        redisTemplate.expire(name,2,TimeUnit.MINUTES);
        return ResultUtils.success(sentence);
    }
    // 未命中獲取鎖
    String LOCK_NAME = "test:redis:lock:" + sequence;
    boolean lock = redisTemplate.opsForValue().get(LOCK_NAME) != null && (boolean) redisTemplate.opsForValue().get(LOCK_NAME);
    //如果lock等于false 那么就可以獲取到鎖并且,鎖住不許其他人操作
    if(!lock){
       return ResultUtils.success(setLockReleaseLockAboutSentence(LOCK_NAME,name,sequence));
    }
    // 沒有獲取到鎖 休眠一段時間,并且反復(fù)檢測redis中的數(shù)據(jù)是否存在,或者鎖是否釋放
    while(true){
        try {
            Thread.sleep(1000);
            log.error("等待中");
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        // 檢查是否存在值
        sentence =  (Sentences) redisTemplate.opsForValue().get(name);
        if(sentence != null){
            return ResultUtils.success(sentence);
        }
        boolean checkAgain = (boolean) redisTemplate.opsForValue().get(LOCK_NAME);
        if(!checkAgain){
            sentence =  setLockReleaseLockAboutSentence(LOCK_NAME,name,sequence);
        }
        return ResultUtils.success(sentence);
    }
}
public Sentences setLockReleaseLockAboutSentence(String LOCK_NAME,String redisName, long sequence){
    // 設(shè)置 鎖值 為true
    setLock(LOCK_NAME);
    // 并且從數(shù)據(jù)中查取數(shù)據(jù)
    Sentences sentence = sentencesService.getById(sequence);
    // 這里為了明顯不能搶鎖設(shè)置一個睡眠時間
    try {
        log.error("休眠中");
        Thread.sleep(3000);
    } catch (InterruptedException e) {
        throw new RuntimeException(e);
    }
//            把數(shù)據(jù)寫入Redis
    redisTemplate.opsForValue().set(redisName,sentence,2, TimeUnit.MINUTES);
    // 釋放鎖
    releaseLock(LOCK_NAME);
    // 返回數(shù)據(jù)
    return sentence;
}

代碼說明,在這個代碼中為了演示明顯,獲取鎖中延遲3s,競爭鎖會延遲1s,下面的演示,初始時Redis中沒有數(shù)據(jù),只能去數(shù)據(jù)庫中取數(shù)據(jù),但是設(shè)置了互斥鎖,所以只能夠一個線程進(jìn)入數(shù)據(jù)庫取數(shù)據(jù),其他只能等待數(shù)據(jù)得到結(jié)果。

結(jié)果示意 redis中無數(shù)據(jù)

在這里插入圖片描述

結(jié)果

在這里插入圖片描述

最終效果是好的。redis中已存入數(shù)據(jù)

到此這篇關(guān)于在SpringBoot中利用Redis實現(xiàn)互斥鎖的文章就介紹到這了,更多相關(guān)SpringBoot互斥鎖內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論

德江县| 大埔县| 志丹县| 望谟县| 琼海市| 扎囊县| 来安县| 巴林右旗| 蒙山县| 黑河市| 闽清县| 亳州市| 嵊泗县| 集安市| 大悟县| 会理县| 白沙| 桦南县| 沧源| 吴旗县| 游戏| 沅陵县| 徐汇区| 荥经县| 溧水县| 剑阁县| 天台县| 铜鼓县| 涟源市| 卢氏县| 威信县| 翼城县| 大埔区| 咸阳市| 酉阳| 开江县| 尼勒克县| 呼和浩特市| 晋州市| 建昌县| 阿城市|