Java基于redis實現(xiàn)分布式鎖(SpringBoot)

分布式鎖,其實原理是就是多臺機(jī)器,去爭搶一個資源,誰爭搶成功,那么誰就持有了這把鎖,然后去執(zhí)行后續(xù)的業(yè)務(wù)邏輯,執(zhí)行完畢后,把鎖釋放掉。

可以通過多種途徑實現(xiàn)分布式鎖,例如利用數(shù)據(jù)庫(mysql等),插入一條記錄(唯一索引),誰插入成功,誰就持有鎖;還可通過zookeeper來實現(xiàn)分布式鎖,誰創(chuàng)建節(jié)點成功,誰就持有鎖。本文介紹通過redis來實現(xiàn)分布式鎖。

本文使用springboot提供的RedisTemplate來操作redis,可以參考我之前的文章【快學(xué)springboot】13.操作redis之String數(shù)據(jù)結(jié)構(gòu),這里對使用RedisTemplate來操作redis做了介紹。當(dāng)然也可以直接使用jedis來操作redis,大家可以參考下jedis的文檔,使用上都是大同小異的。

實現(xiàn)分布式鎖的步驟

第一步:通過redis的setnx方式(不存在則設(shè)置),往redis上設(shè)置一個帶有過期時間的key,如果設(shè)置成功,則獲得了分布式鎖。這里設(shè)置過期時間,是防止在釋放鎖的時候出現(xiàn)異常導(dǎo)致鎖釋放不掉。

第二步:執(zhí)行完業(yè)務(wù)操作之后,刪除該鎖。

實現(xiàn)

新建一個DistributedLock.class,注入StringRedisTemplate。

@ComponentpublicclassDistributedLock{@AutowiredprivateStringRedisTemplate redisTemplate;}

獲得鎖

/**

* 獲得鎖

*/publicbooleangetLock(StringlockId, long millisecond){Booleansuccess = redisTemplate.opsForValue().setIfAbsent(lockId,"lock", millisecond, TimeUnit.MILLISECONDS);returnsuccess !=null&& success; }

setIfAbsent方法,就是當(dāng)鍵不存在的時候,設(shè)置,并且該方法可以設(shè)置鍵的過期時間。該方法對應(yīng)到redis的原生命令就是:

SETlockIdcontentPX millisecond NX

至于設(shè)置多少的過期時間合適,這個是沒有定論的,需要根據(jù)真是的業(yè)務(wù)場景來衡量。

釋放鎖

當(dāng)處理完業(yè)務(wù)邏輯后,需要手動的把鎖釋放掉。

publicvoidreleaseLock(StringlockId){ redisTemplate.delete(lockId); }

釋放鎖的操作比較簡單,直接刪除之前設(shè)置的鍵即可。其實,基于redis實現(xiàn)分布式鎖的方式,在釋放鎖的時候,是存在釋放失敗的風(fēng)險的(比如網(wǎng)路抖動什么的),這也是為什么在設(shè)置鎖的時候需要設(shè)置過期時間的原因,可以防止在出現(xiàn)異常的時候,鎖會自動的消失掉。同時,我們也可以增加幾次失敗之后的重試機(jī)制。


本人親測可用,很簡潔。

原文地址?https://www.cnblogs.com/happy4java/p/11205993.html

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容