分布式中間件:基于 Redis 實現分布式鎖

分布式中間件:基于 Redis 實現分布式鎖

一、背景引入

在當今的互聯網應用中,分布式系統變得越來越常見。在分布式環境下,多個服務實例可能會同時對共享資源進行讀寫操作,這就很容易引發數據不一致等問題。比如電商系統中的庫存扣減,如果多個訂單處理服務同時對同一商品的庫存進行操作,就可能導致超賣現象。為了解決這類問題,分布式鎖應運而生。分布式鎖能夠保證在分布式系統中,同一時刻只有一個服務實例可以對共享資源進行操作,從而確保數據的一致性和完整性。

Redis 作為一款高性能的開源內存數據庫,具有豐富的數據結構和原子操作特性,成為了實現分布式鎖的理想選擇。接下來,我們將深入探討如何基于 Redis 實現分布式鎖。

二、Redis 實現分布式鎖的原理

(一)基本原理

Redis 實現分布式鎖主要是利用了其原子性操作。Redis 提供了 SET 命令,該命令可以原子性地設置一個鍵值對,并且可以同時設置過期時間。當多個客戶端同時嘗試獲取鎖時,只有一個客戶端能夠成功設置該鍵值對,從而獲得鎖。

(二)具體命令

使用 SET key value NX PX timeout 命令,其中:

  • key:表示鎖的名稱,通常是一個具有業務含義的字符串,例如 product:1:lock 表示對商品 ID 為 1 的資源加鎖。
  • value:可以是一個唯一的標識,用于區分不同的客戶端,防止誤解鎖。例如,可以使用 UUID 作為 value。
  • NX:表示只有當鍵不存在時才進行設置操作,如果鍵已經存在,則設置失敗,這保證了同一時刻只有一個客戶端能獲得鎖。
  • PX timeout:設置鍵的過期時間,單位為毫秒。這是為了防止持有鎖的客戶端出現異常(如崩潰)而導致鎖無法釋放,造成死鎖。

三、代碼實現

(一)Java 代碼示例

import redis.clients.jedis.Jedis;
import java.util.UUID;public class RedisDistributedLock {private static final String LOCK_KEY = "my_distributed_lock";private static final int LOCK_EXPIRE_TIME = 5000; // 鎖的過期時間,單位:毫秒private Jedis jedis;public RedisDistributedLock() {this.jedis = new Jedis("localhost", 6379);}public String acquireLock() {String requestId = UUID.randomUUID().toString();String result = jedis.set(LOCK_KEY, requestId, "NX", "PX", LOCK_EXPIRE_TIME);if ("OK".equals(result)) {return requestId;}return null;}public boolean releaseLock(String requestId) {String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";Object result = jedis.eval(script, 1, LOCK_KEY, requestId);return "1".equals(result.toString());}public void close() {jedis.close();}
}

(二)代碼解釋

  • acquireLock 方法:生成一個唯一的 requestId,然后使用 SET 命令嘗試獲取鎖。如果返回 OK,表示成功獲取鎖,返回該 requestId;否則返回 null
  • releaseLock 方法:使用 Lua 腳本確保釋放鎖的操作是原子性的。首先檢查當前鎖的 value 是否與傳入的 requestId 相等,如果相等則刪除該鍵,釋放鎖,并返回 1;否則返回 0。
  • close 方法:關閉 Redis 連接。

(三)使用示例

public class Main {public static void main(String[] args) {RedisDistributedLock lock = new RedisDistributedLock();String requestId = lock.acquireLock();if (requestId != null) {try {System.out.println("成功獲取鎖,開始執行臨界區代碼");// 模擬臨界區代碼執行Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();} finally {lock.releaseLock(requestId);System.out.println("成功釋放鎖");}} else {System.out.println("獲取鎖失敗");}lock.close();}
}

四、Redis 分布式鎖的優缺點

(一)優點

  1. 高性能:Redis 是基于內存的數據庫,讀寫速度非常快,能夠滿足高并發場景下的鎖操作需求。
  2. 原子操作:Redis 提供了原子操作,如 SET 命令和 Lua 腳本,保證了鎖的獲取和釋放操作的原子性,避免了并發問題。
  3. 可擴展性:Redis 可以通過集群或主從復制等方式實現高可用性和可擴展性,滿足大規模分布式系統的需求。

(二)缺點

  1. 單點故障:如果 Redis 節點出現故障,可能會導致鎖服務不可用。雖然可以通過集群或主從復制來解決,但仍然存在一定的風險。
  2. 時鐘漂移:Redis 的鎖超時機制依賴于系統時鐘,如果不同節點的時鐘存在漂移,可能會導致鎖提前或延遲釋放。
  3. 鎖釋放問題:如果客戶端在持有鎖期間崩潰,鎖可能無法正常釋放,需要依賴鎖超時機制來解決。

五、應用場景

  1. 分布式系統中的數據一致性:在多個服務同時訪問和修改共享數據時,使用分布式鎖可以保證數據的一致性。例如,多個訂單處理服務對同一商品的庫存進行操作時,使用分布式鎖可以避免超賣現象。
  2. 任務調度:在分布式任務調度系統中,使用分布式鎖可以保證同一個任務在同一時間只被一個節點執行。例如,定時清理緩存的任務,避免多個節點同時執行導致數據不一致。
  3. 資源限流:在多個客戶端同時訪問有限資源時,使用分布式鎖可以限制同一時間的訪問數量。例如,限制同一時間對某個接口的并發訪問數量。

六、總結

基于 Redis 實現分布式鎖是一種簡單、高效的解決方案,能夠滿足大多數分布式系統的需求。通過合理設置鎖的過期時間和使用原子操作,可以保證鎖的正確性和可靠性。但同時也需要注意 Redis 的單點故障、時鐘漂移等問題,在實際應用中需要根據具體場景進行優化和改進。希望本文能幫助你更好地理解和應用基于 Redis 的分布式鎖。

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

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

相關文章

嘗試使用Tauri2+Django+React項目(2)

前言 嘗試使用tauri2DjangoReact的項目-CSDN博客https://blog.csdn.net/qq_63401240/article/details/146403103在前面筆者不知道怎么做,搞了半天 筆者看到官網,原來可以使用二進制文件,好好好 嵌入外部二進制文件 | Taurihttps://v2.taur…

【006安卓開發方案調研】之大廠APP混合開發方案

基于國內大廠在安卓混合開發領域的實踐,以下是主流解決方案及其核心技術實現路徑的深度解析: 一、主流混合開發解決方案分類 1. Flutter混合開發體系 架構設計 采用組件化分層架構,原生工程作為宿主,通過MethodChannel與Flutter…

Mysql配套測試之查詢篇

&#x1f3dd;?專欄&#xff1a;Mysql_貓咪-9527的博客-CSDN博客 &#x1f305;主頁&#xff1a;貓咪-9527-CSDN博客 “欲窮千里目&#xff0c;更上一層樓。會當凌絕頂&#xff0c;一覽眾山小。” 目錄 條件查詢簡單測試&#xff1a; 1.查詢英語成績不及格的同學(<60) 2…

設計和布局硬件電路是嵌入式系統開發的重要環節

設計和布局硬件電路是嵌入式系統開發的重要環節&#xff0c;涉及從需求分析到原理圖設計、PCB&#xff08;印刷電路板&#xff09;布局以及最終的硬件調試。以下是完整的流程和技術要點&#xff1a; 1. 硬件電路設計的基本流程 1.1 需求分析 明確功能需求&#xff1a;確定系統…

PicFlow:一個圖片處理與上傳工作流工具(圖床上傳工具)

自從學習搭建網站以來&#xff0c;我就把很多圖片托管在七牛云等圖床平臺上。以前總是通過網頁批量上傳&#xff0c;需要登錄并一步步跳轉網頁操作&#xff0c;久而久之就厭煩了&#xff0c;于是花了一天時間用 Python 寫了一個工具 —— PicFlow&#xff0c;從名字可以看出&am…

Web純前端實現在線打開編輯保存PPT幻燈片

很多項目中有時會需要在線打開PPT并編輯保存到服務器。猿大師辦公助手可以完美調用本地office在線打開ppt文件&#xff0c;跟本地打開效果一樣。還可以在線打開word、excel、pdf等文件&#xff0c;支持本機OFFICE完整嵌入模式&#xff0c;本機OFFICE所有功能基本都可以在網頁上…

Android Compose 約束布局(ConstraintLayout、Modifier.constrainAs)源碼深度剖析(十二)

Android Compose 約束布局&#xff08;ConstraintLayout、Modifier.constrainAs&#xff09;源碼深度剖析 一、引言 在 Android 開發中&#xff0c;布局是構建用戶界面的基礎。隨著 Android 開發技術的不斷發展&#xff0c;Jetpack Compose 作為一種全新的聲明式 UI 框架應運…

常考計算機操作系統面試習題(二)(上)

目錄 1. 描述分段內存管理機制 2. 解釋文件分配磁盤塊鏈接分配方法的優點和缺點 3. 進程的狀態有哪些&#xff1f; 4. 一個進程的空間包括哪些部分&#xff1f; 5. 進程和程序的區別&#xff1f; 6. CPU調度可能發生在當一個進程&#xff1a; 7. 哪些條件同時出現&#…

NR SRS Configuration

文章目錄 Frequency PositioningFull-Bandwidth ConfigurationFrequency-Hopping ConfigurationMulti-User ConfigurationsTime-Domain Orthogonal SRSCyclic-Shift Orthogonal SRS Summary and Further ExplorationReferences 此示例展示了如何生成探測參考信號&#xff08;SR…

【行測】言語理解與表達:選詞填空

> 作者&#xff1a;?舊言~ > 座右銘&#xff1a;讀不在三更五鼓&#xff0c;功只怕一曝十寒。 > 目標&#xff1a;掌握選詞填空的基本題型&#xff0c;并能運用到例題中。 > 毒雞湯&#xff1a;有些事情&#xff0c;總是不明白&#xff0c;所以我不會堅持。早安! …

AWS AI中幾個重要的工具介紹

Amazon Bedrock Amazon Bedrock 是使用基礎模型構建和擴展生成式 AI 應用程序的最簡單方式。Amazon Bedrock 是一項全托管服務&#xff0c;通過 API 提供來自亞馬遜和領先 AI 初創公司的基礎模型&#xff0c;因此您可以從各種基礎模型中選擇最適合您用例的模型。借助 Bedrock&…

[項目]基于FreeRTOS的STM32四軸飛行器: 十.檢測遙控器

基于FreeRTOS的STM32四軸飛行器: 十.檢測遙控器 一.檢測遙控器連接邏輯二.遙控器的解鎖情況三.遙控器控制飛機運轉 一.檢測遙控器連接邏輯 判斷是否進入定高模式&#xff1a; 根據返回值判斷遙控器的連接情況&#xff1a; 實現檢測函數&#xff1a; 因為該函數在通信任務中…

Torch.expand等效矩陣相乘

文章目錄 1. description2. pytorch 1. description torch.expand:主要作用是將向量按照指定維度進行復制&#xff0c;expand 可以用全一向量和給定向量以矩陣相乘的方式等效表示n_expand4 2. pytorch torch import torch import torch.nn as nntorch.set_printoptions(pr…

嘗試在軟考65天前開始成為軟件設計師-計算機網絡

OSI/RM 七層模型 層次名功能主要協議7應用層實現具體應用功能 FTP(文件傳輸)、HTTP、Telnet、 POP3(郵件)SMTP(郵件) ------- DHCP、TFTP(小文件)、 SNMP、 DNS(域名) 6表示層數據格式,加密,壓縮.....5會話層建立,管理&終止對話4傳輸層端到端連接TCP,UDP3網絡層分組傳輸&a…

Java 雙端隊列實戰 實現滑動窗口 用LinkedList的基類雙端隊列Deque實現 洛谷[P1886]

集合 關系 介紹 Deque 是一個接口 LinkedList 是這個接口的實現類 題目 輸入輸出 滑動窗口 基于雙端隊列實現 Deque<Integer> deque new LinkedList<>(); 滑動窗口代碼 洛谷 public static List<Integer> maxSlidingWindow(int[] nums, int k) {List&l…

Vue3 集成wangEditor 5

1. 依賴 pnpm install wangeditor/editor --save pnpm install wangeditor/editor-for-vuenext --save2. 在template使用wangEditor 5 v-model數據庫中查詢出來的editor中的數據&#xff0c;數據庫中使用longtext類型 <Toolbarstyle"border-bottom: 1px solid #ccc&q…

Qemu-STM32(十):STM32F103開篇

簡介 本系列博客主要描述了STM32F103的qemu模擬器實現&#xff0c;進行該項目的原因有兩點: 作者在高鐵上&#xff0c;想在STM32F103上驗證一個軟件框架時&#xff0c;如果此時掏出開發板&#xff0c;然后接一堆的線&#xff0c;旁邊的人估計會投來異樣的目光&#xff0c;特別…

QT開發(6)--信號和槽

這里寫目錄標題 1. 信號和槽概述信號的本質槽的本質 2. 信號和槽的使用2.1 連接信號和槽2.2 文檔查詢 3.自定義信號和槽3.1 自定義槽3.2 自定義信號3.3 帶參數的信號和槽 4. 信號和槽的斷開 1. 信號和槽概述 在Qt中&#xff0c;??和控件的每次交互過程稱為?個事件。?如&quo…

【前端】Canvas畫布實現在線的唇膏換色功能

【前端】Canvas畫布實現在線的唇膏換色功能 推薦超級課程: 本地離線DeepSeek AI方案部署實戰教程【完全版】Docker快速入門到精通Kubernetes入門到大師通關課AWS云服務快速入門實戰目錄 【前端】Canvas畫布實現在線的唇膏換色功能背景概述以下是我們的實現方法!第一步 — 找…

異步編程與流水線架構:從理論到高并發

目錄 一、異步編程核心機制解析 1.1 同步與異步的本質區別 1.1.1 控制流模型 1.1.2 資源利用對比 1.2 阻塞與非阻塞的技術實現 1.2.1 阻塞I/O模型 1.2.2 非阻塞I/O模型 1.3 異步編程關鍵技術 1.3.1 事件循環機制 1.3.2 Future/Promise模式 1.3.3 協程&#xff08;Cor…