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

redis和redisson實現(xiàn)分布式鎖的操作方法

 更新時間:2024年03月27日 10:48:51   作者:開心就好啦啦啦  
使用 Redis 實現(xiàn)分布式鎖,最直接的想法是利用 setnx 和 expire 命令實現(xiàn)加鎖,這篇文章主要介紹了redis和redisson實現(xiàn)分布式鎖的操作方法,需要的朋友可以參考下

基于setnx命令的分布式鎖

1. 加鎖

使用 Redis 實現(xiàn)分布式鎖,最直接的想法是利用 setnx 和 expire 命令實現(xiàn)加鎖。

在 Redis 中,setnx 是「set if not exists」如果不存在,則 setnx 的意思,當(dāng)一個線程執(zhí)行 setnx 返回 1,說明 key 不存在,該線程獲得鎖;當(dāng)一個線程執(zhí)行 setnx 返回 0,說明 key 已經(jīng)存在,那么獲取鎖失敗。

SETNX lockKey uniqueValue
(integer) 1
SETNX lockKey uniqueValue
(integer) 0

2. 釋放鎖

釋放鎖的話,直接通過 DEL 命令刪除對應(yīng)的 key 即可。

DEL lockKey
(integer) 1

為了防止誤刪到其他的鎖,這里我們建議使用 Lua 腳本通過 key 對應(yīng)的 value(唯一值)來判斷。選用 Lua 腳本是為了保證解鎖操作的原子性。因為 Redis 在執(zhí)行 Lua 腳本時,可以以原子性的方式執(zhí)行,從而保證了鎖釋放操作的原子性。

if redis.call("get",KEYS[1]) == ARGV[1] then
    return redis.call("del",KEYS[1])
else
    return 0

釋放鎖時,先比較鎖對應(yīng)的 value 值是否相等,value值可以在加鎖的時候把當(dāng)前的線程 ID 當(dāng)做value,并在刪除之前驗證 key 對應(yīng)的 value 是不是自己線程的 ID,避免鎖的誤釋放

3. setnx缺點

setnx 的 key 必須設(shè)置一個超時時間,以保證即使沒有被顯式釋放,這把鎖也要在一定時間后自動釋放??梢允褂胑xpire命令設(shè)置鎖超時時間

4. 存在問題:

setnx 和 expire 不是原子性的操作,假設(shè)某個線程執(zhí)行setnx 命令,成功獲得了鎖,但是還沒來得及執(zhí)行expire 命令,服務(wù)器就掛掉了,這樣一來,這把鎖就沒有設(shè)置過期時間了,變成了死鎖,別的線程再也沒有辦

法獲得鎖了。
解決方案:redis的set命令支持在獲取鎖的同時設(shè)置key的過期時間

基于set命令的分布式鎖

Redis 從 2.6.12 起,SET 涵蓋了 SETEX 的功能,并且 SET 本身已經(jīng)包含了設(shè)置過期時間的功能

使用set命令加鎖并設(shè)置鎖過期時間:

127.0.0.1:6379> SET lockKey uniqueValue EX 3 NX
OK

lockKey:加鎖的鎖名;
uniqueValue:能夠唯一標(biāo)示鎖的隨機字符串;
NX:只有當(dāng) lockKey 對應(yīng)的 key 值不存在的時候才能 SET 成功;
EX:過期時間設(shè)置(秒為單位)EX 3 標(biāo)示這個鎖有一個 3 秒的自動過期時間。與 EX 對應(yīng)的是 PX(毫秒為單位),這兩個都是過期時間設(shè)置。
一定要保證設(shè)置指定 key 的值和過期時間是一個原子操作!?。?/strong> 不然的話,依然可能會出現(xiàn)鎖無法被釋放的問題。

不過,這種解決辦法同樣存在漏洞:如果操作共享資源的時間大于過期時間,就會出現(xiàn)鎖提前過期的問題,進而導(dǎo)致分布式鎖直接失效。如果鎖的超時時間設(shè)置過長,又會影響到性能。

為了解決這個問題,我們可以讓獲得鎖的線程開啟一個守護線程,用來給快要過期的鎖“續(xù)期”。在JAVA的Redisson包中有一個”看門狗”機制,已經(jīng)幫我們實現(xiàn)了這個功能。

redission看門狗分布式鎖

Redisson 中的分布式鎖自帶自動續(xù)期機制,使用起來非常簡單,原理也比較簡單,其提供了一個專門用來監(jiān)控和續(xù)期鎖的 Watch Dog( 看門狗),如果操作共享資源的線程還未執(zhí)行完成的話,Watch Dog 會不斷地延長鎖的過期時間,進而保證鎖不會因為超時而被釋放。

1.加鎖機制

  • 線程去獲取鎖,獲取成功:執(zhí)行l(wèi)ua腳本,保存數(shù)據(jù)到redis數(shù)據(jù)庫。
  • 此時另外一個線程去獲取鎖,可以一直通過while循環(huán)嘗試獲取鎖(鎖重試),
    如果在獲取鎖的最大等待時間內(nèi)加鎖成功,執(zhí)行l(wèi)ua腳本,保存數(shù)據(jù)到redis數(shù)據(jù)庫。如果失敗,則返回加鎖失敗。

2.watch dog自動延期機制:

Redisson在獲取鎖之后,會維護一個看門狗線程,在每一個鎖設(shè)置的過期時間的1/3處,如果線程還沒執(zhí)行完任務(wù),則不斷延長鎖的有效期。剛開始鎖的過期時間默認是30秒,可以通過 lockWactchdogTimeout 參數(shù)來改變。

每過 10 秒,看門狗就會執(zhí)行續(xù)期操作,將鎖的超時時間重置為 30 秒??撮T狗續(xù)期前也會先判斷是否需要執(zhí)行續(xù)期操作,需要才會執(zhí)行續(xù)期,否則取消續(xù)期操作。

看門狗啟動后,對整體性能也會有一定影響,默認情況下看門狗線程是不啟動的。如果使用redisson進行加鎖的同時設(shè)置了鎖的過期時間,也會導(dǎo)致看門狗機制失效。

加鎖的時間默認是30秒,如果加鎖的業(yè)務(wù)沒有執(zhí)行完,那么每隔 30 ÷ 3 = 10秒,就會進行一次續(xù)期,把鎖重置成30秒,保證解鎖前鎖不會自動失效。

3.redisson分布式鎖的關(guān)鍵點:

  • 對key不設(shè)置過期時間,由Redisson在加鎖成功后給維護一個watchdog看門狗,watchdog負責(zé)定時監(jiān)聽并處理,在鎖沒有被釋放且快要過期的時候自動對鎖進行續(xù)期,保證解鎖前鎖不會自動失效
  • 通過Lua腳本實現(xiàn)了加鎖和解鎖的原子操作,底層是使用setnx和lua腳本
  • 通過記錄獲取鎖的客戶端id,每次加鎖時判斷是否是當(dāng)前客戶端已經(jīng)獲得鎖,實現(xiàn)了可重入鎖。

Redisson 的分布式可重入鎖 RLock 為例來說明如何使用 Redisson 實現(xiàn)分布式鎖:

public String testLock() throws InterruptedException {
    RLock lock = redissonClient.getLock("it_lock");
    //嘗試獲取鎖,tryLock參數(shù)分別是:獲取鎖的最大等待時間(期間重試) ,鎖自動釋放時間,時間單位
    //lock.tryLock(10, 30,TimeUnit.SECONDS); //設(shè)置鎖釋放時間 不會續(xù)期操作
    boolean isLock = lock.tryLock(10, TimeUnit.SECONDS); //沒有設(shè)置鎖釋放時間 守護線程會自動續(xù)期
    //是否成功
    if(isLock){
        try {
            //業(yè)務(wù)邏輯
        }finally {
            lock.unlock();
        }
    }
    return "finish";
}

指定鎖超時時間,不會使用自動續(xù)期機制

lock.tryLock(10, 30,TimeUnit.SECONDS); //設(shè)置鎖釋放時間 不會續(xù)期操作

只有未指定鎖超時時間,才會使用到 Watch Dog 自動續(xù)期機制。

   // 手動給鎖設(shè)置過期時間,不具備 Watch Dog 自動續(xù)期機制
   lock.tryLock(10, TimeUnit.SECONDS);

如果使用 Redis 來實現(xiàn)分布式鎖的話,還是比較推薦直接基于 Redisson 來做的

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

相關(guān)文章

  • redis通過位圖法記錄在線用戶的狀態(tài)詳解

    redis通過位圖法記錄在線用戶的狀態(tài)詳解

    這篇文章主要給大家介紹了關(guān)于redis如何通過位圖法記錄在線用戶的狀態(tài)的相關(guān)資料,文中先對位圖進行了一個簡單的介紹,而后通過示例代碼將實現(xiàn)的方法介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2018-11-11
  • Redis解決庫存超賣問題實例講解

    Redis解決庫存超賣問題實例講解

    這篇文章主要介紹了Redis解決庫存超賣問題實例講解,問題和解決辦法都列舉了出來,很貼合實際開發(fā)場景,有需要的同學(xué)可以學(xué)習(xí)下
    2021-03-03
  • Redis預(yù)防緩存穿透的6種策略

    Redis預(yù)防緩存穿透的6種策略

    緩存穿透是指查詢一個根本不存在的數(shù)據(jù),由于緩存不命中,請求會穿透緩存層直接訪問數(shù)據(jù)庫,本文整理了6個Redis預(yù)防緩存穿透的方法,希望對大家有一定的幫助
    2025-04-04
  • 淺談Redis的事件驅(qū)動模型

    淺談Redis的事件驅(qū)動模型

    本文主要介紹了淺談Redis的事件驅(qū)動模型,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-05-05
  • Redis定時任務(wù)原理的實現(xiàn)

    Redis定時任務(wù)原理的實現(xiàn)

    本文主要是基于?redis?6.2?源碼進行分析定時事件的數(shù)據(jù)結(jié)構(gòu)和常見操作,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • Redis分布式鎖防止緩存擊穿的實現(xiàn)

    Redis分布式鎖防止緩存擊穿的實現(xiàn)

    本文主要介紹了Redis分布式鎖防止緩存擊穿的實現(xiàn),文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-01-01
  • Redis 數(shù)據(jù)遷移的項目實踐

    Redis 數(shù)據(jù)遷移的項目實踐

    本文主要介紹了Redis 數(shù)據(jù)遷移的項目實踐,通過Redis-shake的sync(同步)模式,可以將Redis的數(shù)據(jù)實時遷移至另一套Redis環(huán)境,具有一定的參考價值,感興趣的可以了解一下
    2023-09-09
  • 手動實現(xiàn)Redis的LRU緩存機制示例詳解

    手動實現(xiàn)Redis的LRU緩存機制示例詳解

    這篇文章主要介紹了手動實現(xiàn)Redis的LRU緩存機制示例詳解,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-03-03
  • Win10下通過Ubuntu安裝Redis的過程

    Win10下通過Ubuntu安裝Redis的過程

    這篇文章主要介紹了Win10下通過Ubuntu安裝Redis,在安裝Ubuntu需要先打開Windows功能,接著創(chuàng)建一個用戶及密碼,本文給大家介紹的非常詳細,需要的朋友可以參考下
    2022-04-04
  • 分布式緩存redis使用及說明

    分布式緩存redis使用及說明

    Redis單機存在數(shù)據(jù)丟失、并發(fā)低、故障恢復(fù)差和存儲容量有限問題,集群部署通過主從、哨兵和分片解決,結(jié)合RDB/AOF持久化提升數(shù)據(jù)安全與恢復(fù)能力,實現(xiàn)高可用和擴展性
    2025-07-07

最新評論

金沙县| 灵台县| 崇礼县| 安多县| 久治县| 施秉县| 梧州市| 开远市| 宣恩县| 沛县| 无为县| 肥西县| 五台县| 神木县| 蕲春县| 齐齐哈尔市| 娱乐| 江山市| 阿勒泰市| 西盟| 甘孜县| 新安县| 界首市| 金塔县| 淳安县| 久治县| 美姑县| 枣强县| 四会市| 长兴县| 米易县| 北辰区| 开远市| 行唐县| 宝应县| 凤凰县| 会宁县| 兰坪| 年辖:市辖区| 黔西县| 景泰县|