基于Redisson的分布式鎖原理深度解析與優化實踐

基于Redisson的分布式鎖原理深度解析與優化實踐

分布式環境下,鎖的實現至關重要。本文將從技術背景與應用場景出發,結合核心原理、關鍵源碼、實際示例,深入剖析Redisson分布式鎖的實現機制,并給出性能優化建議,幫助后端開發者在高并發場景下穩健落地分布式鎖。

一、技術背景與應用場景

隨著微服務、云原生架構的普及,多個服務實例常常并發訪問同一共享資源,例如:

  • 訂單重復提交防重:避免高并發下生成重復訂單。
  • 庫存并發扣減:保證庫存不出現超賣。
  • 分布式定時任務:集群環境中同節點只執行一次任務。

傳統的JVM層面synchronizedReentrantLock無法跨進程、跨機器使用,需要依賴外部組件。基于Redis的分布式鎖具備高性能、部署簡單、可擴展等優勢,是業界主流選擇之一。Redisson作為一款功能豐富、社區活躍的Redis客戶端,為分布式鎖提供了完整實現。

二、核心原理深入分析

Redisson的分布式鎖主要有以下幾種實現:

  • RLock (可重入鎖)
  • RSemaphore (信號量)
  • RReadWriteLock (讀寫鎖)

本文重點關注RLock的實現原理,核心流程如下:

  1. 客戶端調用lock.lock()時,向Redis發送Lua腳本,該腳本會:
    • 先檢查當前客戶端持有鎖的重入計數,若已持有則直接++并續期。
    • 若無持有,則嘗試設置key(SET NX PX),成功即獲鎖,設置內置看門狗續期機制。
  2. 看門狗機制:Redisson啟動了一個內部定時任務,每隔lockWatchdogTimeout/3毫秒,續期鎖的TTL,以保證長時間業務執行不超時。
  3. 解鎖時,客戶端執行解鎖Lua腳本:
    • 判斷當前clientId是否與鎖中存儲一致,若一致則--重入計數,若計數為0則刪除鎖并取消續期任務。

2.1 Lua腳本核心代碼

-- lock.lua
local key = KEYS[1]
local clientId = ARGV[1]
local ttl = tonumber(ARGV[2])-- 重入
if (redis.call('HEXISTS', key, clientId) == 1) thenredis.call('HINCRBY', key, clientId, 1)redis.call('PEXPIRE', key, ttl)return nil
end-- 初次獲取
if (redis.call('EXISTS', key) == 0) thenredis.call('HSET', key, clientId, 1)redis.call('PEXPIRE', key, ttl)return nil
end-- 其他客戶端已占用,返回剩余TTL
return redis.call('PTTL', key)

2.2 看門狗(LockWatchdog)實現

Redisson在org.redisson.lock包下實現了看門狗續期任務:

public class LockWatchdog extends ScheduledService {private final String lockName;public LockWatchdog(...){ }@Overridepublic void run() {try {// 發送續期命令,延長TTLcommandExecutor.evalWriteAsync(..., RScript.Mode.READ_WRITE, unlockScript, RScript.ReturnType.STATUS, Arrays.asList(lockName), clientId, lockWatchdogTimeout);} catch (Exception e) {log.error("Lock watchdog renew error", e);}}
}

默認lockWatchdogTimeout為30秒,業務執行時間小于該值時可不設置自定義TTL。

三、關鍵源碼解讀

3.1 鎖實例生成

RLock lock = redisson.getLock("order:lock");
public class RedissonLock implements RLock {private final CommandAsyncExecutor commandExecutor;private final String name;private final long lockWatchdogTimeout;public void lock() {lock(DEFAULT_ACQUIRY_RETRY_MILLIS, DEFAULT_TIMEOUT, TimeUnit.MILLISECONDS);}public void lock(long leaseTime, TimeUnit unit) {// leaseTime為-1時,啟用看門狗續期internalLock(leaseTime, unit);}
}

3.2 加鎖的內部邏輯

private void internalLock(long leaseTime, TimeUnit unit) {long threadId = Thread.currentThread().getId();String clientId = getClientId(threadId);long ttl = unit.toMillis(leaseTime) > 0 ? unit.toMillis(leaseTime) : lockWatchdogTimeout;while (true) {Long result = tryAcquireAsync(leaseTime, unit).get();if (result == null) {// 獲得鎖,啟動Watchdog續期scheduleWatchdog(clientId);return;}Thread.sleep(DEFAULT_ACQUIRY_RETRY_MILLIS);}
}

四、實際應用示例

以下示例展示如何在Spring Boot項目中引入Redisson分布式鎖:

  1. 引入依賴:
<dependency><groupId>org.redisson</groupId><artifactId>redisson-spring-boot-starter</artifactId><version>3.17.6</version>
</dependency>
  1. 配置文件(application.yml):
redisson:address: "redis://127.0.0.1:6379"lockWatchdogTimeout: 30000
  1. 業務代碼:
@Service
public class OrderService {private final RLock orderLock;private final RedissonClient redissonClient;@Autowiredpublic OrderService(RedissonClient client) {this.redissonClient = client;this.orderLock = redissonClient.getLock("order:lock");}public void createOrder(String userId) {orderLock.lock();try {// 核心業務:檢查庫存、寫入訂單表processOrder(userId);} finally {orderLock.unlock();}}
}

五、性能特點與優化建議

  1. watchDog續期帶來額外心跳開銷,可根據業務情況調小lockWatchdogTimeout或顯式指定leaseTime
  2. 高并發場景下熱點鎖可能成為瓶頸,可結合Redisson的RPermitExpirableSemaphore分布式信號量進行限流降級。
  3. 對比Zookeeper實現的分布式鎖,Redisson更輕量,適合高TPS場景,但Redis單點故障需配合哨兵/集群部署。
  4. 對鎖競爭激烈的場景,可采用業務層面分段鎖(Hash槽分段)或增強鍵前綴隨機化,降低熱點。
  5. 監控鎖的使用情況:結合Redisson API獲取當前線程持有信息,并結合Prometheus采集告警。

總結:本文從原理到實踐,全面解析了基于Redisson的分布式鎖機制并提供優化建議,旨在幫助開發者在高并發生產環境中穩健落地。

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

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

相關文章

室外 3DVG 基準

室外 3DVG基準&#xff08;按重要性與被引用頻率&#xff09; Talk2Car / Talk2Car-3D (2019 / 衍生) — 對象 referral&#xff08;駕駛場景&#xff09; 說明&#xff1a;最早的自然語言 → 駕駛場景對象引用數據集之一&#xff08;原 Talk2Car 是以 nuScenes 為底并提供自然…

Jenkins安裝部署(Win11)和常見配置鏡像加速

一、安裝前準備 本文使用的Jenkins Windows一鍵安裝包&#xff0c;JDK事先配置好環境變量&#xff0c;Jenkins版本&#xff1a; Jenkins下載地址&#xff1a;jenkins一鍵安裝包v2-479-1.msi資源-CSDN下載 二、Jenkins安裝部署 1、下載Jenkins &#xff0c;點擊下一步下一步…

Windows MCP.Net:革命性的 .NET Windows 桌面自動化 MCP 服務器

&#x1f4cb; 目錄 項目概述 核心技術架構 功能特性詳解 技術實現亮點 安裝與配置 實戰應用場景 代碼示例與API詳解 性能優化與最佳實踐 未來發展規劃 總結 項目概述 在人工智能快速發展的今天&#xff0c;AI 助手與操作系統的深度集成成為了一個重要趨勢。Window…

Java ArrayList的介紹及用法

十分想念順店雜可。。。ArrayList 是 Java 集合框架中最常用的類之一&#xff0c;實現了 List 接口&#xff0c;底層基于動態數組實現&#xff0c;支持動態擴容&#xff0c;相比普通數組更靈活。以下是其詳細介紹及用法&#xff1a;一、核心特性動態大小&#xff1a;無需預先指…

Docker 命令大全及使用場景總結

一、容器生命周期管理1. 創建并運行容器docker run [選項] 鏡像名 [命令]常用選項&#xff1a;-d&#xff1a;后臺運行&#xff08;detached&#xff09;-it&#xff1a;交互式終端&#xff08;如 -it ubuntu bash&#xff09;--name&#xff1a;指定容器名稱-p 主機端口:容器端…

簡單的 HTTPS 學習

簡單的 HTTPS 學習 1. 需求 現在使用的服務是HTTP調用形式&#xff0c;服務可能會有調用外圍https形式的服務&#xff0c;簡單了解了一下&#xff0c;然后寫了一個簡單的例子進行記錄。 HTTP&#xff08;超文本傳輸協議&#xff09; 是一種用于傳輸超文本的應用層協議&#…

[系統架構設計師]系統質量屬性與架構評估(八)

[系統架構設計師]系統質量屬性與架構評估&#xff08;八&#xff09; 一.軟件系統質量屬性 1.基本概念 軟件系統質量屬性&#xff1a;可測量或可測試的屬性 開發期質量屬性&#xff0c;運行期質量屬性面向架構評估的質量屬性&#xff1a;1.可用性&#xff1a; 提升策略 錯誤檢測…

【R語言】R 語言中 gsub 與正則表達式詳解(含 POSIX 與 Perl 風格實例)

R 語言中 gsub 與正則表達式詳解&#xff08;含 POSIX 與 Perl 風格實例&#xff09; 在 R 語言中&#xff0c;字符串處理是非常常見的需求&#xff0c;R 語言中的 gsub() 函數則具有字符串替換的功能。本文將通過兩個實例&#xff0c;幫助你深入理解 R 的 gsub()、POSIX 字符…

EN55035多媒體設備電磁兼容性抗干擾要求標準

EN55035 是一項由歐洲標準化委員會制定的電磁兼容性&#xff08;EMC&#xff09;標準&#xff0c;全稱為《多媒體設備的電磁兼容性要求》。該標準主要針對多媒體設備的電磁輻射和抗干擾能力進行規范&#xff0c;確保這類設備在電磁環境中能夠正常工作&#xff0c;同時不對其他設…

計算分組內時間列的最大差值

計算分組內時間列的最大差值 在 Pandas 中&#xff0c;要計算每個分組內 time 列的最大值與當前行值的差值&#xff0c;需結合 groupby() 和 transform() 方法。核心步驟如下&#xff1a;分組計算最大值 使用 transform(max) 獲取每個分組中 time 列的最大值&#xff0c;結果會…

CUDA 編程筆記:CUDA延遲隱藏

一、核心概念&#xff1a;延遲隱藏&#xff08;Latency Hiding&#xff09;是 GPU 通過多線程機制掩蓋指令延遲的關鍵技術。當某些線程束&#xff08;warp&#xff09;因指令延遲&#xff08;如內存訪問或算術計算&#xff09;而等待時&#xff0c;其他就緒線程束會立即被調度執…

MySQL工具包中的其他程序

雖然有很多不同的程序&#xff0c;但有些選項是公共的&#xff0c;比兔用戶名和密碼&#xff0c;使用方法和MySQL相同&#xff0c;在這里統一列出&#xff0c;后面我們介紹不同的工具時&#xff0c;只討論個性的選項以及作用以下是常用的MySQL程序&#xff1a;程序名作用mysqld…

C#WPF實戰出真汁09--【消費開單】--選擇菜品

1、功能介紹當選擇一個空桌時&#xff0c;必須先開臺才能開單&#xff0c;可以先開臺&#xff0c;再開單&#xff0c;也可以開臺的同時開單當選擇一個用餐中的餐桌時&#xff0c;必須顯示該桌前面已經點好的菜品&#xff0c;同時可以繼續點餐或結賬所以無論哪個功能都涉及選擇菜…

大廠語音合成成本深度對比:微軟 / 阿里 / 騰訊 / 火山 API 計費拆解與技術選型指南

在 AI 配音、智能客服、教育音頻等場景爆發的當下&#xff0c;語音合成 API 已成為企業技術棧中的核心組件。然而&#xff0c;不同云廠商的計費規則差異顯著&#xff0c;短文本 / 長文本計費分離、預付費 / 后付費價格梯度懸殊、音色授權費暗藏成本陷阱等問題&#xff0c;常導致…

Flutter開發 網絡請求

HttpClient&#xff08;dart自有&#xff09; 1.get 點擊請求按鈕獲取數據&#xff0c;解析數據獲取單詞展示到屏幕上。class MyState extends State {String info "暫無數據";List<Widget> texts [];overridevoid initState() {super.initState();}override…

vscode中用python調用matlab的函數(環境安裝)

本實踐適用于WIN11-x64和ubuntu22.04-x64系統&#xff0c;其余系統和架構未驗證。 效果展示 1.環境要求 MATLAB Engine API for Python 的系統要求&#xff1a;參閱此官方文檔MATLAB 與 Python 的版本兼容性&#xff1a;參閱此官方文檔 2.安裝步驟 安裝Vscode&#xff08;不…

【數據分享】大清河(大慶河)流域上游土地利用

而今天要說明數據就是大清河&#xff08;大慶河&#xff09;流域上游土地利用。數據介紹大清河&#xff0c;又稱大慶河&#xff0c;作為海河流域的重要支流&#xff0c;其流域上游地區不僅是區域水資源調控的關鍵節點&#xff0c;更是生態保護與經濟發展的重要載體。以下從地理…

圖論——Djikstra最短路

原理解釋 首先解釋一下它大概的應用場景以及原理&#xff1a;現在有這么一張圖&#xff0c;圖上各點之間都有一定的邊權或者說是距離。給定你一個起點&#xff08;例如點1&#xff09;&#xff0c;讓你求這個點到圖上所有點的最短距離是多少&#xff1f; 這個問題比較平常&…

kafka初步介紹

Kafka角色介紹TopicTopic主題的意思&#xff0c;消費者必須指定主題用于的消息發送&#xff0c;生產者也必須指定主題用于消息的接收。topic只是邏輯上的劃分。partitionpartition是分區的意思&#xff0c;他的主要作用是將發送到一個topic的數據做一個劃分。如果有4個partitio…

windows10的vs2019編譯openssl靜態庫備忘

1、下載安裝openssl源碼2、官網下載安裝activeperl或Strawberry Perl。官網下載慢&#xff0c;網盤找找。使用中activeperl有些異常提示、缺模塊&#xff0c;最后使用了Strawberry Perl。3、安裝nasm。powershell使用choco install nasm -y 即可。powershell使用cd命令打開當前…