欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

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

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

基本知識

前提條件,有一個(gè)能夠在Springboot中使用Redis的項(xiàng)目,或者能夠直接開也行

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

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

在這里插入圖片描述

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

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

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

具體實(shí)現(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));
}

具體流程實(shí)現(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);
    // 命中返回?cái)?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));
    }
    // 沒有獲取到鎖 休眠一段時(shí)間,并且反復(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è)置一個(gè)睡眠時(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);
    // 返回?cái)?shù)據(jù)
    return sentence;
}

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

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

在這里插入圖片描述

結(jié)果

在這里插入圖片描述

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

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

相關(guān)文章

  • 在eclipse中使用SVN的方法(圖文)

    在eclipse中使用SVN的方法(圖文)

    這篇文章主要介紹了在eclipse中使用SVN的方法(圖文),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-08-08
  • Java中ArrayList的使用方法簡單介紹

    Java中ArrayList的使用方法簡單介紹

    這篇文章主要為大家簡單介紹了Java中ArrayList的使用方法,針對ArrayList去重問題進(jìn)行擴(kuò)展分析,感興趣的小伙伴們可以參考一下
    2016-07-07
  • 使用SpringSecurity 進(jìn)行自定義Token校驗(yàn)

    使用SpringSecurity 進(jìn)行自定義Token校驗(yàn)

    這篇文章主要介紹了使用SpringSecurity 進(jìn)行自定義Token校驗(yàn)操作,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-06-06
  • SpringBoot?將配置文件掛到?jar?包外面的操作方法

    SpringBoot?將配置文件掛到?jar?包外面的操作方法

    在 SpringBoot 中,可以將配置文件放在 jar 包外面,這樣可以方便地修改配置而不需要重新打包和部署,這篇文章主要介紹了SpringBoot?如何將配置文件掛到?jar?包外面,需要的朋友可以參考下
    2023-03-03
  • java Class文件內(nèi)部結(jié)構(gòu)解析過程詳解

    java Class文件內(nèi)部結(jié)構(gòu)解析過程詳解

    java class的文件結(jié)構(gòu),java class文件結(jié)構(gòu)是基于字節(jié)流的,用unicode進(jìn)行編碼,下面說說java Class文件內(nèi)部結(jié)構(gòu)分析
    2013-11-11
  • 使用Java第三方實(shí)現(xiàn)發(fā)送短信功能

    使用Java第三方實(shí)現(xiàn)發(fā)送短信功能

    這篇文章主要介紹了使用Java第三方實(shí)現(xiàn)發(fā)送短信功能,在一些開發(fā)中,經(jīng)常需要有給用戶發(fā)送短信接收驗(yàn)證碼的功能,那么在Java中該如何實(shí)現(xiàn)呢,今天我們就一起來看一看
    2023-03-03
  • 基于sharding-jdbc的使用限制

    基于sharding-jdbc的使用限制

    這篇文章主要介紹了sharding-jdbc的使用限制,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-10-10
  • Java數(shù)據(jù)結(jié)構(gòu)之復(fù)雜度篇

    Java數(shù)據(jù)結(jié)構(gòu)之復(fù)雜度篇

    算法復(fù)雜度分為時(shí)間復(fù)雜度和空間復(fù)雜度。其作用:?時(shí)間復(fù)雜度是度量算法執(zhí)行的時(shí)間長短;而空間復(fù)雜度是度量算法所需存儲空間的大小
    2022-01-01
  • Mybatis-flex整合達(dá)夢數(shù)據(jù)庫的實(shí)現(xiàn)示例

    Mybatis-flex整合達(dá)夢數(shù)據(jù)庫的實(shí)現(xiàn)示例

    本文討論了國產(chǎn)達(dá)夢數(shù)據(jù)庫與Mybatis-flex框架的整合過程,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-10-10
  • Spring cloud 查詢返回廣告創(chuàng)意實(shí)例代碼

    Spring cloud 查詢返回廣告創(chuàng)意實(shí)例代碼

    在本篇文章里小編給大家整理的是關(guān)于Spring cloud 查詢返回廣告創(chuàng)意實(shí)例代碼,需要的朋友們可以跟著學(xué)習(xí)下。
    2019-08-08

最新評論