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

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:能夠唯一標示鎖的隨機字符串;
NX:只有當(dāng) lockKey 對應(yīng)的 key 值不存在的時候才能 SET 成功;
EX:過期時間設(shè)置(秒為單位)EX 3 標示這個鎖有一個 3 秒的自動過期時間。與 EX 對應(yīng)的是 PX(毫秒為單位),這兩個都是過期時間設(shè)置。
一定要保證設(shè)置指定 key 的值和過期時間是一個原子操作?。?! 不然的話,依然可能會出現(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優(yōu)惠券秒殺企業(yè)實戰(zhàn)

    Redis優(yōu)惠券秒殺企業(yè)實戰(zhàn)

    本文主要介紹了Redis優(yōu)惠券秒殺企業(yè)實戰(zhàn),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-07-07
  • 詳解用Redis實現(xiàn)Session功能

    詳解用Redis實現(xiàn)Session功能

    本篇文章主要介紹了用Redis實現(xiàn)Session功能,具有一定的參考價值,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。
    2016-12-12
  • redis中token失效引發(fā)的一次生產(chǎn)事故

    redis中token失效引發(fā)的一次生產(chǎn)事故

    項目再測試的時候發(fā)現(xiàn)不定時token失效,本文主要介紹了redis中token失效引發(fā)的一次生產(chǎn)事故,文中通過示例代碼介紹的非常詳細,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-03-03
  • Redis數(shù)據(jù)庫安裝部署及基本操作詳解

    Redis數(shù)據(jù)庫安裝部署及基本操作詳解

    這篇文章主要介紹了Redis數(shù)據(jù)庫安裝部署及基本操作,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-08-08
  • 控制Redis的hash的field中的過期時間

    控制Redis的hash的field中的過期時間

    這篇文章主要介紹了控制Redis的hash的field中的過期時間問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-01-01
  • redis中List列表常見命令及使用場景

    redis中List列表常見命令及使用場景

    這篇文章主要給大家介紹了關(guān)于redis中List列表常見命令及使用場景的相關(guān)資料,Redis列表是簡單的字符串列表,按照插入順序排序,文中通過代碼介紹的非常詳細,需要的朋友可以參考下
    2024-01-01
  • Redis內(nèi)存碎片原理深入分析

    Redis內(nèi)存碎片原理深入分析

    這篇文章主要為大家介紹了Redis內(nèi)存碎片原理深入分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-02-02
  • 詳解redis集群選舉機制

    詳解redis集群選舉機制

    這篇文章主要介紹了詳解redis集群選舉機制,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-03-03
  • Linux下redis的安裝與使用圖文教程

    Linux下redis的安裝與使用圖文教程

    這篇文章主要介紹了Linux下redis的安裝與使用,結(jié)合圖文形式分析了Linux環(huán)境下redis的下載、編譯、安裝、部署、訪問等相關(guān)操作技巧,需要的朋友可以參考下
    2019-08-08
  • redis復(fù)制有可能碰到的問題匯總

    redis復(fù)制有可能碰到的問題匯總

    這篇文章主要介紹了redis復(fù)制有可能碰到的問題匯總,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-04-04

最新評論