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

前言

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

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

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

實現分布式鎖的步驟

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

第二步:執行完業務操作之后,刪除該鎖。

實現

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

@Component
public class DistributedLock {
?@Autowiredprivate StringRedisTemplate redisTemplate;
?
}

獲得鎖

/*** 獲得鎖*/public boolean getLock(String lockId, long millisecond) {Boolean success = redisTemplate.opsForValue().setIfAbsent(lockId, "lock",millisecond, TimeUnit.MILLISECONDS);return success != null && success;}

setIfAbsent方法,就是當鍵不存在的時候,設置,并且該方法可以設置鍵的過期時間。該方法對應到redis的原生命令就是:

SET lockId content PX millisecond NX 

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

釋放鎖

當處理完業務邏輯后,需要手動的把鎖釋放掉。

 public void releaseLock(String lockId) {redisTemplate.delete(lockId);}

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

測試

新建一個BusinessTask.java,代碼如下:

@Component
public class BusinessTask {
?private final static String LOCK_ID = "happyjava";
?@AutowiredDistributedLock distributedLock;
?@Scheduled(cron = "0/10 * * * * ? ")public void doSomething() {boolean lock = distributedLock.getLock(LOCK_ID, 10 * 1000);if (lock) {System.out.println("執行任務");distributedLock.releaseLock(LOCK_ID);} else {System.out.println("沒有搶到鎖");}}
?
}

這里使用了springboot的Scheduled注解來實現定時任務,該cron表達式的意思是每10秒鐘,執行一次任務,然后我們啟動兩次該項目,觀察一段時間執行結果:

第一個springboot任務:

基于redis實現分布式鎖(Java)

第二個springboot任務:

基于redis實現分布式鎖(Java)

兩個任務在交替的執行任務,證明了同一時刻只有一個應用持有了鎖。

總結

本文主要介紹了如何使用Java代碼(springboot的restTemplate)實現Redis分布式鎖,對于加鎖和解鎖也分別給出了示例代碼。其實我們還可以嘗試使用Redisson實現分布式鎖,這是Redis官方提供的Java組件,這個后續再介紹吧。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/386561.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/386561.shtml
英文地址,請注明出處:http://en.pswp.cn/news/386561.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

請談下Android消息機制,復習指南

談起Android框架體系架構,我先提個問:什么是Android框架體系架構 ? Android系統構架是安卓系統的體系結構,android的系統架構和其操作系統一樣,采用了分層的架構,共分為四層,從高到低分別是And…

SVN Cannot merge into a working copy that has local modifications

我嘗試了 主支,分支都提交,但是依然無法合并。 最終,我在服務器上將分支刪除,然后主支在拷貝過去。 一,打開服務器資源 二,刪除分支 三,拷貝主支到分支 四,刷新分支,就能…

資深Android開發帶你入門Framework,再不刷題就晚了!

想要成為一名優秀的Android開發,你需要一份完備的知識體系,在這里,讓我們一起成長為自己所想的那樣。 本文參考了目前大部分 Android 應用啟動優化的方案,將大家的方案做一個匯總,如果你有這方面的需求,只…

K8S相關內容

常用工具:docker linux k8s kubeadm 概念 etcd 數據庫 類似redis api server 接口對外提供api 調用 可以命令 kubectl 或者 kube-proxy,能訪問etcd,事件總線 scheduler 調度決策的組件 掌握新的情況,進行決策及分布pod放在哪些n…

資深Android開發帶你入門Framework,架構師必備技能

開頭 先說一下我大概的情況吧。渣本畢業,工作已經有快兩年了,從高中就開始玩小破站。無論是學習還是日常放松都是在b站。大學主學的軟件技術專業,所以,進大學校門那一刻起,去上海bilibili工作就在心里埋下了種子。在學…

Java——線程鎖,死鎖,等待喚醒機制

一、線程鎖 線程安全問題 其實,線程安全問題都是由全局變量及靜態變量引起的。若每個線程中對全局變量、靜態變量只有讀操作,而無寫操作,一般來說,這個全局變量是線程安全的;若有多個線程同時執行寫操作,…

資深大牛帶你了解源碼!關于Android程序員最近的狀況,大廠內部資料

前言 回顧一下自己這段時間的經歷,因公司突然通知裁員,我匆匆忙忙地出去面了幾家,但最終都沒有拿到offer,我感覺今年的寒冬有點冷。公司開始第二波裁員,我決定主動拿賠償走人。后續的面試過程我做了一些準備&#xff…

AE 新建項目(一)(持續更新,做到哪算哪)

開發環境 工具:Visual Studio 2012、ArcEngine10.4.1 語言:C# 開發步驟 1、打開Visual Studio 2012,選擇新建項目,創建一個.NET Framework4的,Windows窗體應用程序。取名Demo 2、工具箱中,拖一個splitConta…

基于redis分布式鎖實現的多線程并發程序

前兩個版本的代碼 都或多或少存在一定的問題,雖然可能微乎其微,但是程序需要嚴謹再嚴謹, 第一個版本問題: 局限于單機版,依賴于 Jvm的鎖 第二個版本問題: 極端情況下,解鎖邏輯的問題&#xf…

day15 Ui自動化元素的定位

day15 元素的定位Ui自動化元素的定位1、火狐瀏覽器安裝try xpath2、元素定位思路:(1)查看頁面元素,確認能夠唯一定位到元素的屬性,比如id,文案3、學習xpath cssSelector 手寫定位方式xpath(xpat…

幾張圖可以理解GC JVM調優的內容

public class ApiPurchaseOrderServiceApp {public static void main(String[] args) throws Exception {ApiPurchaseOrderServiceApp mnew ApiPurchaseOrderServiceApp();m.compute();//棧System.out.println("ok");//方法出口}public int compute(){int a1;//局部…

靈魂拷問!一起刷完了這份1307頁的安卓面試寶典吧,不吃透都對不起自己

前言 每個程序員都有一個夢想,那就是進一線互聯網公司深造,不要跟我說你不想進去,如果給你一個這樣的平臺,不管是薪資待遇還是接觸的高度來說,對我們程序員來說都是一個機會,我以前有一個同事,…

ShardingSphere分庫分表實戰

ShardingSphere是一套開源的分布式數據庫中間件解決方案組成的生態圈,它由Sharding-JDBC、Sharding-Proxy和Sharding-Sidecar(計劃中)這3款相互獨立的產品組成。 他們均提供標準化的數據分片、分布式事務和數據庫治理功能,可適用于…

靈魂拷問!細數Android開發者的艱辛歷程,成功入職阿里

什么是中年危機 根據權威數據顯示,國內IT程序員鼎盛時期是在25-27歲左右,30歲對于程序員而言完全是一個38線,接著就是轉業轉崗的事情,這一點在業界也算是一個共識了。 大學畢業步入IT行業普遍年齡也是在22歲左右,然而…

React 深度學習:ReactFiber

packages/react-reconciler/src/ReactFiber.js Fiber // A Fiber is work on a Component that needs to be done or was done. There can // be more than one per component. // Fiber 是 Component 上需要完成或已經完成工作。每個組件可以有多個 fiber。 export type Fiber…

JMM模型到并發編程

電腦:內存 L1 L2 L3 緩存 CPU ctrlatldel就可以看到 Java 有線程內存,在執行線程的時候,會從主內存把變量加載到工作內存(緩存),所以,在多線程同時改變一個靜態變量時候,實際是分開…

焦慮的移動互聯網開發者如何破局?專題解析

尷尬的35歲 不知道是哪個人提出的職場35歲就要面臨被淘汰的定律,因為35歲定律本來就是個偽命題,尤其是在IT行業! 現在年八九百萬的大學生畢業,他們雖然年輕活力,但是很多企業也將之“拒之門外”。 35歲的不要,二十幾…

17.前端路由router-07keep-alive

keep-alive是Vue提供的一個抽象組件,用來對組件進行緩存,從而節省性能, 由于是一個抽象組件,所以在v頁面渲染完畢后不會被渲染成一個DOM元素 當組件在keep-alive內被切換時組件的activated、deactivated這兩個生命 周期鉤子函數會…

jvm指令碼

建議直接復制保存至本地,研究jvm運行,執行指令非常有幫助 一、未歸類系列A 此系列暫未歸類。 指令碼 助記符 說明 0x00 nop 什么都不做 0x01 aconst_null 將null推送至棧頂 二、const系列 該系列命令主要負責把簡單的數值類型送到棧頂。該系列命令不帶參…

來一份全面的面試寶典練練手,面試真題解析

前言 下面的題目都是大家在面試字節跳動或者其它大廠面試時經常遇到的,如果大家有好的題目或者好的見解歡迎分享。 參考解析:郭霖、鴻洋 內容特點:條理清晰,含圖像化表示更加易懂。 內容概要:包括 Handler、Activi…