redission實現讀寫鎖的原理

Redisson 實現分布式讀寫鎖的核心原理是 ?基于 Redis 的 Lua 腳本原子操作? + ?Pub/Sub 通知機制,在保證強一致性的同時實現高效的讀并發(讀不阻塞讀,寫阻塞讀)。以下是其核心設計:


?一、核心數據結構?

Redisson 使用 Redis 的 ?Hash 結構? 存儲鎖信息:

  • ?Key:?{鎖名稱}(如?my_lock
  • ?Hash 字段:
    • mode: 鎖模式(read/write
    • UUID:threadId: 持有鎖的客戶端標識(如?c983678b-1421-4c76-8ea0-7f3ab7d9c775:1
    • count: 鎖的重入次數(支持可重入)

?二、讀鎖(Read Lock)實現原理?

?1. 獲取讀鎖流程?
-- Lua 腳本原子執行
if (redis.call('exists', KEYS[1]) == 0) then  -- 無任何鎖redis.call('hset', KEYS[1], ARGV[2], 1);  -- 創建讀鎖redis.call('pexpire', KEYS[1], ARGV[1]);  -- 設置超時return nil;
end;
if (redis.call('hexists', KEYS[1], ARGV[2]) == 1) then  -- 當前線程已持有讀鎖redis.call('hincrby', KEYS[1], ARGV[2], 1);         -- 重入次數+1redis.call('pexpire', KEYS[1], ARGV[1]);            -- 刷新超時return nil;
end;
if (redis.call('hexists', KEYS[1], 'mode') == 1) and (redis.call('hget', KEYS[1], 'mode') == 'read') then  -- 已有其他讀鎖redis.call('hincrby', KEYS[1], ARGV[2], 1);         -- 直接疊加讀鎖計數redis.call('pexpire', KEYS[1], ARGV[1]);return nil;
end;
return redis.call('pttl', KEYS[1]);  -- 存在寫鎖,返回剩余時間(需等待)

?關鍵點?:

  • 只要當前無寫鎖(mode?非?write),讀鎖可直接獲取,?不阻塞其他讀鎖
  • 多個讀鎖共享同一個 Hash 結構,通過字段區分不同客戶端。
?2. 讀鎖釋放?
if (redis.call('hexists', KEYS[1], ARGV[2]) == 0) then return nil; end;  -- 鎖不存在
local counter = redis.call('hincrby', KEYS[1], ARGV[2], -1);  -- 重入次數-1
if (counter == 0) thenredis.call('hdel', KEYS[1], ARGV[2]);  -- 移除當前線程的鎖
end;
if (redis.call('hlen', KEYS[1]) == 1) then  -- 只剩 mode 字段(無任何鎖)redis.call('del', KEYS[1]);              -- 刪除整個 Keyredis.call('publish', KEYS[2], ARGV[1]); -- 發布解鎖通知
end;
return 1;

?三、寫鎖(Write Lock)實現原理?

?1. 獲取寫鎖流程?
if (redis.call('exists', KEYS[1]) == 0) then  -- 無任何鎖redis.call('hset', KEYS[1], 'mode', 'write');  -- 設置為寫模式redis.call('hset', KEYS[1], ARGV[2], 1);       -- 記錄持有者redis.call('pexpire', KEYS[1], ARGV[1]);       -- 設置超時return nil;
end;
if (redis.call('hexists', KEYS[1], 'mode') == 1) and (redis.call('hget', KEYS[1], 'mode') == 'write') then  -- 已有寫鎖if (redis.call('hexists', KEYS[1], ARGV[2]) == 1) then  -- 當前線程持有寫鎖redis.call('hincrby', KEYS[1], ARGV[2], 1);         -- 重入次數+1redis.call('pexpire', KEYS[1], ARGV[1]);return nil;end;
end;
return redis.call('pttl', KEYS[1]);  -- 存在讀鎖或其他寫鎖,返回剩余時間(需等待)

?關鍵點?:

  • 寫鎖要求絕對互斥:?必須無任何鎖(讀/寫)存在才能獲取。
  • 若存在讀鎖或其他寫鎖,客戶端需等待(通過 Pub/Sub 監聽解鎖通知)。
?2. 寫鎖釋放?
if (redis.call('hexists', KEYS[1], ARGV[3]) == 0) then return nil; end;  -- 鎖不存在
local counter = redis.call('hincrby', KEYS[1], ARGV[3], -1);  -- 重入次數-1
if (counter == 0) thenredis.call('hdel', KEYS[1], ARGV[3]);  -- 移除持有者
end;
if (redis.call('hlen', KEYS[1]) == 1) then  -- 只剩 mode 字段redis.call('del', KEYS[1]);             -- 刪除 Keyredis.call('publish', KEYS[2], ARGV[1]); -- 發布解鎖通知
end;
return 1;

?四、阻塞等待與通知機制?

?1. 鎖競爭時的等待策略?
  • 當鎖獲取失敗時,Redisson ?不輪詢,而是通過 Redis 的 ?Pub/Sub 訂閱鎖釋放事件?:
    // 偽代碼:訂閱解鎖通知
    RedisPubSub listener = new RedisPubSub() {void onMessage(String channel, String message) {if (message.equals("unlock_msg")) {tryAcquireLock(); // 收到通知后重新嘗試獲取鎖}}
    };
    redis.subscribe(listener, "lock_channel");
  • ?優勢?:避免頻繁輪詢 Redis,減少網絡開銷。
?2. 鎖超時與續期?
  • ?看門狗機制(Watchdog)??:
    后臺線程每隔 10 秒檢查鎖是否仍被持有,若持有則刷新 TTL(默認 30 秒),防止業務未完成時鎖過期。
    if (lockAcquired) {scheduleExpirationRenewal(threadId); // 啟動看門狗線程
    }

?五、公平鎖實現?

Redisson 還提供公平讀寫鎖?(按請求順序獲取鎖):

  1. 使用 Redis ?List 結構作為請求隊列。
  2. 每個客戶端獲取鎖前在隊列尾部追加自己的請求 ID。
  3. 只有隊首的請求有權嘗試獲取鎖,避免饑餓問題。

?總結:Redisson 讀寫鎖的核心優勢?

  1. ?讀讀并發?:通過 Hash 結構疊加讀鎖計數,無寫鎖時讀操作永不阻塞。
  2. ?原子性?:所有鎖操作通過 Lua 腳本在 Redis 單線程中執行,無競態條件。
  3. ?低開銷等待?:基于 Pub/Sub 的事件通知取代輪詢。
  4. ?容錯性?:鎖超時自動釋放 + 看門狗續期,避免死鎖。
  5. ?可重入?:支持同一線程多次加鎖(通過?count?字段實現)。

??:實際代碼比上述偽代碼更復雜(含重試機制、異常處理等),但核心邏輯一致。建議直接閱讀?Redisson 源碼?中的?RedissonReadLock?和?RedissonWriteLock?類。

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

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

相關文章

【 ??SQL注入漏洞靶場】第二關文件讀寫

SQLi-Labs?它是一個開源的、專門為學習 ??Web安全?? 和 ??SQL注入技術?? 而設計的靶場項目。開發者故意在代碼中留下了各種不同類型的SQL注入漏洞,讓安全研究人員、學生和愛好者可以在一個合法、安全的環境中進行實戰練習,從而掌握發現和利用SQ…

設計藝術~緩存結構設計

背景 面對高QPS場景的業務,不得不考慮對一些數據做緩存設計,常見的緩存設計有這些:DB Proxy緩存、分布式緩存、Localcache緩存。 在考慮加緩存的背景下不考慮數據的一致性,都是瞎扯,所以我們再定義一下數據的一致性場景…

后端開發技術棧

后端開發技術棧核心技術內容平臺 (Content Platform)電商 (E-Commerce)金融科技 (FinTech) / 支付物聯網 (IoT - Internet of Things)游戲后端 (Game Backend)社交平臺搜索平臺企業級應用開發音視頻處理后端地圖與地理位置服務DevOps大數據開發大模型應用開發智能合約開發核心技…

【ICCV2025】計算機視覺|即插即用|ESC:顛覆Transformer!超強平替,ESC模塊性能炸裂!

論文地址:https://arxiv.org/pdf/2503.06671 代碼地址:https://github.com/dslisleedh/ESC 關注UP CV縫合怪,分享最計算機視覺新即插即用模塊,并提供配套的論文資料與代碼。 https://space.bilibili.com/473764881 摘要 本研究…

【面試場景題】如何進行高并發系統的性能測試?

文章目錄一、明確測試目標與指標二、測試環境搭建三、測試工具選型四、測試場景設計五、執行測試與監控六、瓶頸分析與調優七、測試報告與迭代總結高并發系統的性能測試是驗證系統在極限流量下是否能保持穩定運行的關鍵環節,需要結合場景設計、工具選型、指標監控、…

攻防世界ReverseMe-120

這道題比較經典,涉及三個知識點,所以記錄一下。首先給了一個文件,detect it easy看了下,是32位exe。放入ida中,找下main函數,F5反編譯看一下偽代碼。int __cdecl main(int argc, const char **argv, const …

小白也能看懂,HTTP中的文件上傳與下載到底發生了什么?

HTTP 文件傳輸協議解析:上傳與下載 這份文檔會用最簡單的方式,帶你了解 HTTP 協議是如何處理文件下載和上傳的。我們會專注于協議本身,看看客戶端(比如你的瀏覽器)和服務端(網站服務器)之間到底…

快速構建數據集-假數據(生成劃分)

快速構建數據集-假數據1、torch.randn(?)2、HuggingFace Datasets(?)🔹1. 從字典生成🔹2. 從 pandas.DataFrame 生成🔹3. 批量生成“業務型”假數據(配合 Faker)&#…

[修訂版]Xenomai/IPIPE源代碼情景解析

[修訂版]Xenomai/IPIPE源代碼情景解析 第一章:Interrupt Pipeline介紹 1.1 I-pipe與Xenomai1.2 I-pipe核心概念1.3 拉取I-pipe代碼 第二章:I-pipe對ARM64異常的改造 2.1 ARM64中斷機制與異常處理2.2 EL0_IRQ 中斷改造之入口2.3 EL0_IRQ 中斷改造之中斷處…

【Qt開發】按鈕類控件(三)-> QCheckBox

目錄 1 -> 概述 2 -> 核心特性 2.1 -> 狀態管理 2.2 -> 信號機制 2.3 -> 外觀與文本 3 -> 應用場景 4 -> 代碼示例 5 -> 總結 1 -> 概述 QCheckBox 是 Qt 框架中提供的一個基礎控件,用于實現復選框功能。它允許用戶在兩種或三種…

在新發布的AI論文中 pytorch 和tensorflow 的使用比例

根據 2025 年最新的學術動態和行業報告,PyTorch 在 AI 論文中的使用比例已占據絕對主導地位,而 TensorFlow 的占比持續下降。以下是基于多個權威來源的綜合分析: 一、頂級會議中的框架分布 在 NeurIPS、ICML、CVPR 等頂級學術會議中&#xff…

3DXML格式是什么?用什么軟件可以打開?

3DXML 是一種開放標準的數據交換格式,主要用于三維 CAD(計算機輔助設計)模型的存儲和交換。它是由 Dassault Systmes 開發的一種文件格式,常用于 CATIA V6 和其他支持該格式的應用程序中。3DXML 文件可以包含完整的 3D 模型數據&a…

9月8日星期一今日早報簡報微語報早讀

9月8日星期一,農歷七月十七,早報#微語早讀。1、中國火箭與月亮同框,遙感四十號03組衛星發射成功;2、湖南郴州開發區改革:編制數由815名減至680名,精簡16.6%;3、水利部對廣東、廣西啟動洪水防御Ⅳ…

windows系統搭建MQTT服務器

1、MQTT 協議 MQTT協議:實現MQTT協議需要客戶端和服務器端通訊完成。 三種身份: 發布者(Publish)、代理(Broker)(服務器)、訂閱者(Subscribe)。 消息的發布者和訂閱者都是客戶端,消息代理是服務器,消息發布者可以同時是訂閱者。 MQTT&am…

從 GPT 到 LLaMA:解密 LLM 的核心架構——Decoder-Only 模型

🔥從 GPT 到 LLaMA:解密 LLM 的核心架構——Decoder-Only 模型 “為什么所有大模型(LLM)都長一個樣?” 因為它們都有一個共同的“基因”——Decoder-Only 架構。 在前面兩節中,我們學習了: BER…

Codeforces Round 1047 (Div. 3)

由于最近這三天的數學建模,讓我這個精力本來就不多的AI手更加力竭了,沒注意到昨晚的cf,所以今天來補題了。 比賽連接:比賽傳送門 A題: You are doing a research paper on the famous Collatz Conjecture. In your e…

C++經典的數據結構與算法之經典算法思想:貪心算法(Greedy)

貪心算法(Greedy Algorithm):通過局部最優達成全局最優的決策策略 貪心算法是一種通過每次選擇局部最優解來期望全局最優解的算法思想。它不考慮未來的影響,僅根據當前信息做出最優選擇,適用于具有貪心選擇性質和最優子…

LangChain實戰(二十一):構建自動化AI客服系統

本文是《LangChain實戰課》系列的第二十一篇,將帶領您構建一個完整的自動化AI客服系統。通過結合對話記憶、工具調用和業務知識庫,我們將創建一個能夠處理復雜客戶查詢的智能客服解決方案。 前言 在現代商業環境中,客戶服務是企業成功的關鍵因素之一。傳統客服系統往往面臨…

一人公司智能管理系統概述

系統概述 項目結構 Al_Compny系統采用前后端分離的全棧架構,項目根目錄下包含兩個主要子目錄:Al_Compny_backend(后端服務)和Al_Compny_frontend(前端應用)。核心功能模塊 Al_Compny系統是一個面向"一…

OpenWrt | 在 PPP 撥號模式下啟用 IPv6 功能

文章目錄一、WAN 口配置二、LAN 口配置三、IPv6 測試本文將詳細介紹 將光貓的網絡模式改成橋接之后使用路由器撥號的上網方式的情況下,在 OpenWrt 上使用 PPP 撥號模式上網時,啟用 IPv6 功能的方法。 一、WAN 口配置 首先,我們需要在 網絡 …