日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

SpringBoot实现Redis分布式锁

發布時間:2025/3/19 javascript 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 SpringBoot实现Redis分布式锁 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前言

當不同的進程,必須以獨占資源的方式實現資源共享,就需要用到分布式鎖。

安全和穩定性

分布式鎖的實現,必須滿足以下2個特性

  • 獨享互斥:在任意一個時刻,只能有一個客戶端持有鎖
  • 無死鎖:既然有加鎖,則必須存在解鎖。即使持有鎖的客戶端崩潰宕機,鎖仍然允許被其他客戶端獲取,不能造成無限期的等待

例子1

@Autowired private StringRedisTemplate stringRedisTemplate;@GetMapping("/lock") public void lock1() throws InterruptedException {String lockKey = "lockKey", lockValue = "lockValue";Boolean success = stringRedisTemplate.opsForValue().setIfAbsent(lockKey, lockValue, Duration.ofSeconds(10));if (success){try{System.out.println(String.format("Thread-%d:Success", Thread.currentThread().getId()));}finally {stringRedisTemplate.delete(lockKey);}} }
  • 獨享互斥:setIfAbsent等同于Redis的SETNX命令,當key不存在才生效,返回的是true;當key存在時返回false。
  • 無死鎖:setIfAbsent第3個參數是key超時時間,就算中途應用服務掛了,等時間到了key自動失效。另外,finally處理刪除key操作,及時釋放鎖。

用JMeter發送1000個并發請求,結果如下:

Thread-227:Success Thread-88:Success Thread-116:Success Thread-202:Success Thread-185:Success Thread-97:Success

但是,上述Demo存在以下問題:

  • 客戶端A獲取到鎖資源,同時設置超時時間10s,緊接著A被其他操作堵塞了進程
  • 10s過后,由于A的業務尚未執行完,鎖過期自動失效了
  • 客戶端B成功獲取鎖資源
  • 此時A的業務邏輯執行完畢,做了釋放鎖操作,此時刪除的KEY是客戶端B加鎖的KEY
  • 客戶端C嘗試獲取鎖資源,由于KEY已經被A刪掉了,所以C也加鎖成功,和客戶端B存在了并發的問題
  • 例子2

    public void lock3() throws InterruptedException {String lockKey = "lockKey";//lock value改成唯一性的UUIDString lockValue = UUID.randomUUID().toString();Boolean success = stringRedisTemplate.opsForValue().setIfAbsent(lockKey, lockValue, Duration.ofSeconds(10));if (success){try{System.out.println(String.format("Thread-%d:Success", Thread.currentThread().getId()));}finally {//釋放鎖不再是簡單的DELETE KEYreleaseLock(lockKey, lockValue);}} } private boolean releaseLock(String key, String value){String srcValue = stringRedisTemplate.opsForValue().get(key);if (StrUtil.isEmpty(srcValue)){return true;}else if (srcValue.equals(value)){stringRedisTemplate.delete(key);return true;}return false; }

    上面增加了releaseLock函數:

  • 先從Redis取出KEY
  • 如果KEY不存在,說明已經過期了,這里直接return true,當做釋放鎖資源成功
  • 如果KEY存在,把VALUE和加鎖時用的UUID做比較,相等就說明這是自己占用的鎖資源,直接DELETE;如果不相等,就不要做DELETE操作,說明這是其他客戶端加的鎖
  • 擴展鎖

    如果你的業務邏輯可以拆解成多個小步驟,可以將鎖的有效時間設置短一些。在業務處理的過程中,當發現KEY的有效期很短時,再次延長其有效期(前提還是key存在并且value是之前設置的value)

    總結

    以上是生活随笔為你收集整理的SpringBoot实现Redis分布式锁的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。