使用Redis的SETNX命令實現分布式鎖

什么是分布式鎖

分布式鎖是一種用于在分布式系統中控制多個節點對共享資源進行訪問的機制。在分布式系統中,由于多個節點可能同時訪問和修改同一個資源,因此需要一種方法來確保在任意時刻只有一個節點能夠對資源進行操作,以避免數據不一致或沖突。分布式鎖就是用來實現這種互斥訪問的工具。

為什么 Redis 的 SETNX 可以實現分布式鎖

Redis 的 SETNX 命令(即 SET if Not eXists)可以用來實現分布式鎖,原因如下:

  1. 原子性SETNX 是一個原子操作,這意味著在同一時間只有一個客戶端能夠成功設置鍵值對。如果鍵已經存在,SETNX 將不會執行任何操作。這種原子性確保了鎖的獲取和釋放是線程安全的。

  2. 唯一性SETNX 確保了鎖的唯一性。只有第一個嘗試設置鍵的客戶端能夠成功,其他客戶端在嘗試設置相同的鍵時會失敗。這模擬了鎖的“獲取”和“釋放”行為。

  3. 過期時間:通過結合 EXPIRE 命令或使用 SET 命令的 EX 選項,可以為鎖設置一個過期時間。這防止了鎖被永久占用,即使客戶端在持有鎖期間崩潰或未能正確釋放鎖。

  4. 分布式環境:Redis 是一個分布式內存數據庫,可以在多個節點之間共享數據。因此,使用 Redis 實現的鎖可以在分布式系統中的多個節點之間共享,從而實現分布式鎖。

  5. 高性能:Redis 是一個高性能的數據庫,能夠處理大量的并發請求。這使得 Redis 非常適合作為分布式鎖的實現基礎。

準備工作

創建一個Spring Boot項目,并引入相關依賴

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

application.yml文件中配置 Redis 連接信息:

server:port: 8080
spring:redis:host: xxx.xxx.xxx.xxxport: 6379password: xxxxxx

具體實現

創建分布式鎖工具類

import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;import java.util.concurrent.TimeUnit;@Component
public class DistributedLock {private final StringRedisTemplate redisTemplate;// 通過構造函數注入 StringRedisTemplatepublic DistributedLock(StringRedisTemplate redisTemplate) {this.redisTemplate = redisTemplate;}/*** 嘗試獲取分布式鎖** @param lockKey    鎖的鍵* @param requestId  請求標識,用于區分不同的鎖持有者* @param expireTime 鎖的過期時間,單位為毫秒* @return 如果成功獲取鎖,返回 true;否則返回 false*/public boolean acquireLock(String lockKey, String requestId, long expireTime) {// 使用 setIfAbsent 方法嘗試設置鍵值對,如果鍵不存在則設置成功并返回 true,否則返回 falseBoolean result = redisTemplate.opsForValue().setIfAbsent(lockKey, requestId, expireTime, TimeUnit.MILLISECONDS);return result != null && result;}/*** 釋放分布式鎖** @param lockKey   鎖的鍵* @param requestId 請求標識,用于確保只有鎖的持有者才能釋放鎖* @return 如果成功釋放鎖,返回 true;否則返回 false*/public boolean releaseLock(String lockKey, String requestId) {// 獲取當前鎖的值String currentValue = redisTemplate.opsForValue().get(lockKey);// 檢查當前鎖的值是否等于請求標識,確保只有鎖的持有者才能釋放鎖if (currentValue != null && currentValue.equals(requestId)) {// 刪除鎖鍵return redisTemplate.delete(lockKey);}return false;}
}

創建業務類用來測試

import com.wh.demo01.demos.web.utils.DistributedLock;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.util.Date;@Service
public class MyRedisService {private final DistributedLock distributedLock;// 通過構造函數注入 DistributedLock@Autowiredpublic MyRedisService(DistributedLock distributedLock) {this.distributedLock = distributedLock;}/*** 模擬需要同步執行的方法*/public void someMethod() {String lockKey = "myLockKey";String requestId = "uniqueRequestId";long expireTime = 10000; // 10 secondstry {// 嘗試獲取鎖if (distributedLock.acquireLock(lockKey, requestId, expireTime)) {// 獲取到鎖,執行需要同步的操作System.out.println(new Date() + "獲取鎖成功");// 模擬業務操作Thread.sleep(5000);} else {System.out.println(new Date() + "獲取鎖失敗");}} catch (InterruptedException e) {Thread.currentThread().interrupt();} finally {// 確保鎖在操作完成后被釋放distributedLock.releaseLock(lockKey, requestId);}}
}

創建Controller

import com.wh.demo01.demos.web.service.MyRedisService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
@RequestMapping("/redis")
public class RedisController {@Autowiredprivate MyRedisService service;@GetMapping("/test")public void TestRedis(){service.someMethod();}
}

整個項目結構如下:
在這里插入圖片描述
使用idea的復制配置功能將該服務復制一份,并指定端口為8081,模擬分布式服務:
在這里插入圖片描述
使用接口調試工具分別向80808081端口發送請求:
在這里插入圖片描述
在這里插入圖片描述
結果如下:
在這里插入圖片描述
在這里插入圖片描述
可見在分布式鎖的影響下,someMethod方法在10秒內只能被調用一次。

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

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

相關文章

白騎士的C++教學高級篇 3.1 文件操作

系列目錄 上一篇&#xff1a;白騎士的C教學進階篇 2.4 標準模板庫&#xff08;STL&#xff09; 文件操作是C編程中的一個重要部分&#xff0c;允許程序與外部存儲設備進行交互&#xff0c;從而實現數據的持久化存儲和讀取。C標準庫提供了豐富的文件操作功能&#xff0c;包括文…

嵌入式香橙派人工智能AI開發板詳細操作與遠程聊天實現

大家好&#xff0c;今天給大分享一個OrangePi AIpro&#xff08;20T&#xff09;采用昇騰作為主控芯片的開發板&#xff0c;開箱以及對應功能的詳細實現。 第一&#xff1a;板子基本介紹 接通電源給對應的開發板上電&#xff0c;觀察其中的現象&#xff0c;如下&#xff1a; 注…

基于HAL庫的stm32的OLED顯示屏顯示(IIC)

OLED OLED&#xff0c;即有機發光二極管( Organic Light Emitting Diode )。OLED由于同時具備自發光&#xff0c;不需背光源、對比度高、厚度薄、視角廣、反應速度快、可用于撓曲性面板、使用溫度范圍廣、構造及制程較簡單等優異之特性&#xff0c;被認為是下一代的平面顯示器…

龍國專利局瑞數6

聲明(lianxi a15018601872) 本文章中所有內容僅供學習交流使用&#xff0c;不用于其他任何目的&#xff0c;抓包內容、敏感網址、數據接口等均已做脫敏處理&#xff0c;嚴禁用于商業用途和非法用途&#xff0c;否則由此產生的一切后果均與作者無關&#xff01; 前言(lianxi a…

富文本中提取信息并去除其中的HTML或XML標簽

要從富文本中提取信息并去除其中的HTML或XML標簽&#xff0c;可以使用不同的編程語言和庫。以下是一些流行語言中的示例方法&#xff1a; 1. Python&#xff08;使用BeautifulSoup&#xff09; BeautifulSoup是一個強大的Python庫&#xff0c;用于從HTML或XML文件中提取數據。…

巨魔商店(TrollStore)介紹與使用指南

iOS巨魔商店&#xff08;TrollStore&#xff09;介紹與使用指南 引言 在iOS系統中&#xff0c;App Store是官方唯一的應用下載渠道&#xff0c;但這也限制了用戶獲取非官方或破解版應用的可能性。然而&#xff0c;巨魔商店&#xff08;TrollStore&#xff09;的出現打破了這一…

配置和保護SSH

使用SSH訪問遠程命令行 描述Secure Shell SSH&#xff08;Secure Shell&#xff09; 是一種網絡協議&#xff0c;用于在不安全的網絡上安全地進行系統管理和數據傳輸。它最初由 Tatu Ylnen 于1995年設計&#xff0c;并成為保護網絡服務免受攻擊的標準。SSH提供了多種功能&…

開始構建我們自己的大語言模型:數據處理部分

關注本專欄&#xff08;NLP簡論&#xff1a;手搓大語言模型實踐&#xff09; 繼續學習從頭編寫、訓練自己的大語言模型。 接上集&#xff0c;本章我們將深入說一下大語言模型數據處理部分的細節&#xff0c;并直接提供本部分的完整代碼。 【配套資源】 暫時的詞匯表&#xff1…

GNN論文粗讀

論文 文章目錄 論文基于異構圖的GNN論文GNN領域論文環境領域GNN論文 隨緣更新 基于異構圖的GNN論文 Distance Information Improves Heterogeneous Graph Neural Networks:DOI: 10.1109/TKDE.2023.3300879 轉導和歸納任務&#xff0c;創新點&#xff1a;異構距離編碼HDE提高GN…

關于Vue中涉及到大量數據的級聯菜單樹狀結構的數據多選勾選頁面卡頓卡死問題

項目場景&#xff1a;如題 提示&#xff1a;有個需求&#xff0c;級聯菜單樹狀結構的數據高達3萬多條&#xff0c;多選&#xff0c;只需要最后一層級value 原因分析&#xff1a;頁面一下子渲染大量數據會導致瀏覽器內存暴漲100%&#xff0c;導致頁面卡死&#xff0c;而且eleme…

常見Linux目錄和配置文件

目錄 /boot/&#xff1a;開機配置文件&#xff0c;也是存放核心vmlinuz的地方 /bin/&#xff1a;系統可執行文件目錄&#xff0c;CentOS7后合并到/usr/bin中&#xff0c;并鏈接過去 /sbin/&#xff1a;系統管理員常用指令存放目錄&#xff0c;例如開關機、磁盤分區等指令&am…

基于SpringBoot+Vue的廣場舞團系統(帶1w+文檔)

基于SpringBootVue的廣場舞團系統(帶1w文檔) 基于SpringBootVue的廣場舞團系統(帶1w文檔) 廣場舞團&#xff0c;為用戶隨時隨地查看廣場舞團信息提供了便捷的方法&#xff0c;更重要的是大大的簡化了管理員管理廣場舞團信息的方式方法&#xff0c;更提供了其他想要了解廣場舞團…

基于Trace的類型特化動態語言JIT編譯

文章目錄 Explain一、簡介二、一個跟蹤運行的示例三、跟蹤樹3.1 Traces類型特化&#xff08;Type specialization&#xff09; 3.2 Trace Trees3.3 黑名單&#xff08;Blacklisting&#xff09; 四、嵌套跟蹤樹4.1 Nesting Algorithm4.2 Blacklisting with Nesting 五、跟蹤樹優…

Java NIO 面試題及答案整理,最新面試題

Java NIO中的Buffer有哪些主要類型? Java NIO中的Buffer用于與NIO通道進行交互,作為基本的數據容器。主要類型包括: 1、ByteBuffer: 最常用的類型,用于存儲字節數據。 2、CharBuffer: 用于存儲字符數據。 3、DoubleBuffer、FloatBuffer、IntBuffer、LongBuffer、Short…

【Pytorch】一文向您詳細介紹 torch.randn_like()

&#x1f389;&#x1f525;【Pytorch】一文向您詳細介紹 torch.randn_like() &#x1f525;&#x1f389; 下滑即可查看博客內容 &#x1f308; 歡迎蒞臨我的個人主頁 &#x1f448;這里是我靜心耕耘深度學習領域、真誠分享知識與智慧的小天地&#xff01;&#x1f387; …

滑動窗口題目

題目描述&#xff1a; 計算兩個字符串str1和str2在給定的含有n個元素的字符串數組strs中出現的最短距離。 詳細解釋&#xff1a; 定義整數變量n&#xff0c;用于存儲字符串數組strs的長度。定義一個vector<string>類型的變量strs&#xff0c;用于存儲輸入的字符串。定義…

破解反爬蟲策略 /_guard/auto.js(一) 原理

背景 當用代碼或者postman訪問一個網站的時候&#xff0c;訪問他的任何地址都會返回<script src"/_guard/auto.js"></script>&#xff0c;但是從瀏覽器中訪問顯示的頁面是正常的&#xff0c;這種就是網站做了反爬蟲策略。本文就是帶大家來破解這種策略&…

輕松搞定一鍵切換主題色?分享 1 段優質 CSS 代碼片段!

本內容首發于工粽號&#xff1a;程序員大澈&#xff0c;每日分享一段優質代碼片段&#xff0c;歡迎關注和投稿&#xff01; 大家好&#xff0c;我是大澈&#xff01; 本文約 800 字&#xff0c;整篇閱讀約需 1 分鐘。 今天分享一段優質 CSS 代碼片段&#xff0c;輕松實現一鍵切…

4.3 最小二乘近似

一、最小二乘解 A x b A\boldsymbol x\boldsymbol b Axb 經常無解&#xff0c;一般是因為方程太多了。矩陣 A A A 的行比列要多&#xff0c;即方程要多余未知數&#xff08; m > n m>n m>n&#xff09;。 n n n 個列只能張成 m m m 空間的一小部分&#xff0c;除非…

spring中的依賴注入

文章目錄 spring中的依賴注入一、Autowired二、Qualifier三、Resource四、總結 spring中的依賴注入 這里主要講述三個注解裝配 一、Autowired 作用&#xff1a;自動按照類型注入。只要容器中唯一的一個bean對象類型和要注入的變量類型匹配&#xff0c;就可以注入成功。 如果i…