分布式鎖: Redisson紅鎖(RedLock)原理與實現細節


分布式鎖是分布式系統的核心基礎設施,但 單節點 Redis 鎖在高可用場景下存在致命缺陷:當 Redis 主節點宕機時,從節點可能因異步復制未完成而丟失鎖信息,導致多個客戶端同時持有鎖。為此,Redis 作者 Antirez 提出了 RedLock 算法,旨在通過多節點協作提升分布式鎖的可靠性。本文將深入剖析 Redisson 中 RedLock 的實現原理、技術爭議與最佳實踐。


一、單節點 Redis 鎖的局限性

1. 主從架構下的鎖丟失問題

假設以下場景:

  1. 客戶端 A 在 Redis 主節點成功獲取鎖。
  2. 主節點宕機,鎖尚未同步到從節點。
  3. 從節點晉升為新主節點,此時客戶端 B 也能獲取同一把鎖。
  4. 結果:客戶端 A 和 B 同時持有鎖,違反互斥性。

2. 異步復制的風險

Redis 主從復制默認異步,鎖的寫入可能在故障切換后丟失。


二、RedLock 算法核心思想

RedLock 的核心是通過 多個獨立的 Redis 節點(至少 5 個)協作實現分布式鎖。算法步驟如下:

1. 加鎖流程

  1. 向所有節點發起加鎖請求
    客戶端依次向 N 個獨立 Redis 節點發送加鎖命令:

    SET lock_key <unique_value> NX PX <expire_time>
    
    • 使用相同的 Key 和唯一值(如 UUID + 線程ID)。
    • 設置合理的過期時間(通常為 10-30 秒)。
  2. 計算有效鎖數量
    客戶端統計成功獲得鎖的節點數。若 多數節點(≥ N/2 +1) 返回成功,則認為加鎖成功。
    示例:N=5 時,至少需要 3 個節點成功。

  3. 計算鎖的實際持有時間
    鎖的最終有效時間 = 初始過期時間 - 加鎖過程耗時。

    • 若實際持有時間過短(如剩余時間 < 業務執行時間),需立即釋放鎖。

2. 釋放鎖流程

向所有節點發送釋放鎖的 Lua 腳本(無論是否加鎖成功):

if redis.call("get",KEYS[1]) == ARGV[1] thenreturn redis.call("del",KEYS[1])
elsereturn 0
end

三、Redisson 中 RedLock 的實現

1. 配置多節點 Redisson 客戶端

需為每個獨立 Redis 節點創建 RedissonClient 實例:

Config config1 = new Config();
config1.useSingleServer().setAddress("redis://node1:6379");
RedissonClient client1 = Redisson.create(config1);Config config2 = new Config();
config2.useSingleServer().setAddress("redis://node2:6379");
RedissonClient client2 = Redisson.create(config2);// ... 創建其他節點客戶端RLock lock1 = client1.getLock("myLock");
RLock lock2 = client2.getLock("myLock");
RLock lock3 = client3.getLock("myLock");RedissonRedLock redLock = new RedissonRedLock(lock1, lock2, lock3);

2. 加鎖的底層邏輯

調用 redLock.lock() 時,Redisson 內部執行以下步驟:

  1. 向所有節點并行發起加鎖請求
    使用異步線程池同時向 N 個節點發送加鎖命令。

  2. 統計成功加鎖的節點數

    • 若成功節點數 ≥ 多數(如 5 節點需 ≥3),則加鎖成功。
    • 否則,向所有節點發送解鎖命令,并拋出 LockException
  3. 啟動看門狗續期(可選)
    若未指定 leaseTime,Redisson 會為所有成功節點啟動看門狗線程,定期續期鎖。

3. 解鎖流程

調用 redLock.unlock() 時:

  1. 向所有節點發送解鎖命令
    即使某些節點加鎖失敗,也需嘗試解鎖。

  2. 處理部分節點失敗
    若某些節點解鎖失敗(如網絡問題),Redisson 會記錄日志,但不會重試(需業務層處理)。


四、RedLock 的技術爭議與應對策略

1. 爭議點

1.1 時鐘跳躍問題
  • 場景:若某 Redis 節點發生時鐘跳躍(如 NTP 同步導致時間回撥),可能導致鎖提前過期。
  • Redisson 的應對
    默認依賴 Redis 服務器的系統時間,建議禁用自動時鐘同步(或在物理機環境運行)。
1.2 網絡延遲與 GC 停頓
  • 場景:客戶端因 GC 停頓或網絡延遲,誤判鎖已釋放。
  • 解決思路
    • 鎖過期時間應遠大于業務最大執行時間(如設置 30 秒,業務執行時間 ≤10 秒)。
    • 使用唯一 Token(unique_value)確保只有鎖持有者能釋放鎖。
1.3 算法安全性爭議

Martin Kleppmann 在 How to do distributed locking 中指出:

  • RedLock 依賴「系統模型假設」(如無時鐘跳躍、無長時間 GC),在異步模型下無法保證絕對安全。
  • 推薦使用基于 ZooKeeper/etcd 的 CAS 操作 替代。

Antirez 的回應 Is Redlock safe?:

  • RedLock 在 實踐中的大多數場景 下足夠安全,但需權衡場景需求。

2. 使用建議

  • 適用場景:對鎖的可靠性要求高,可容忍極低概率的鎖失效(如非金融場景)。
  • 規避方案
    • 結合業務冪等性 + 狀態機,即使鎖失效也能保證最終一致性。
    • 使用 Fencing Token(遞增令牌)防止過期鎖操作資源(需存儲層支持)。

五、RedLock 性能優化

1. 節點數量選擇

  • 建議節點數:5 或 7(容錯能力與性能的平衡)。
  • 容錯能力公式:允許宕機節點數 = (N-1)/2。

2. 超時時間設置

  • 加鎖超時:建議 50-200ms(避免長時間阻塞)。
  • 鎖過期時間:業務最大執行時間的 2-3 倍。

3. 異步加鎖優化

使用 tryLockAsync() 實現非阻塞加鎖:

RedissonRedLock redLock = new RedissonRedLock(lock1, lock2, lock3);
RFuture<Boolean> future = redLock.tryLockAsync(100, 10, TimeUnit.SECONDS);
future.whenComplete((res, ex) -> {if (res) {// 加鎖成功}
});

六、對比其他方案

方案優點缺點適用場景
Redis 單節點鎖高性能、簡單主從切換可能丟鎖非關鍵業務、低并發
RedLock高可靠性(多節點容錯)性能較低、實現復雜高可靠性要求
ZooKeeper 鎖CP 模型、強一致性性能差、依賴 ZK 集群金融、政務系統
etcd 鎖高并發、強一致性(Raft 協議)功能較簡單Kubernetes 生態、高并發

七、總結

Redisson 的 RedLock 實現通過多節點協作,顯著提升了分布式鎖的可靠性,但其復雜性、性能損耗和潛在風險(如時鐘問題)需謹慎評估。技術選型建議

  • 常規場景:優先使用單節點 Redis 鎖(結合業務冪等性)。
  • 高可靠場景:評估 RedLock 或轉向 ZooKeeper/etcd。
  • 混合方案:對關鍵資源使用 RedLock,非關鍵資源使用單節點鎖。

最終,分布式鎖的可靠性不僅依賴中間件,還需結合業務層的容錯設計(如事務補償、異步校對),才能構建健壯的分布式系統。

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

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

相關文章

c++多態面試題之(析構函數與虛函數)

有以下問題展開 析構函數要不要定義成虛函數&#xff1f;基類的析構函數要不要定義成虛函數&#xff1f;如果不定義會有什么問題&#xff0c;定義了在什么場景下起作用。 1. 基類析構函數何時必須定義為虛函數&#xff1f; 當且僅當通過基類指針&#xff08;或引用&#xff09;…

Python高級進階:Vim與Vi使用指南

李升偉 整理 在 Python 高級進階中&#xff0c;使用 Vim 或 Vi 作為代碼編輯器可以顯著提升開發效率&#xff0c;尤其是在遠程服務器開發或快速腳本編輯時。以下是關于它們在 Python 開發中的高級應用詳解&#xff1a; 1. Vim/Vi 簡介 Vi&#xff1a;經典的 Unix 文本編輯器…

Dify中使用插件LocalAI配置模型供應商報錯

服務器使用vllm運行大模型&#xff0c;今天在Dify中使用插件LocalAI配置模型供應商后&#xff0c;使用工作流的時候&#xff0c;報錯&#xff1a;“Run failed: PluginInvokeError: {"args":{},"error_type":"ValueError","message":&…

深度學習驅動下的目標檢測技術:原理、算法與應用創新(二)

三、主流深度學習目標檢測算法剖析 3.1 R - CNN 系列算法 3.1.1 R - CNN 算法詳解 R - CNN&#xff08;Region - based Convolutional Neural Networks&#xff09;是將卷積神經網絡&#xff08;CNN&#xff09;應用于目標檢測領域的開創性算法&#xff0c;其在目標檢測發展歷…

【Umi】項目初始化配置和用戶權限

app.tsx import { RunTimeLayoutConfig } from umijs/max; import { history, RequestConfig } from umi; import { getCurrentUser } from ./services/auth; import { message } from antd;// 獲取用戶信息 export async function getInitialState(): Promise<{currentUse…

[學習] RTKLib詳解:qzslex.c、rcvraw.c與solution.c

RTKLib詳解&#xff1a;qzslex.c、rcvraw.c與solution.c 本文是 RTKLlib詳解 系列文章的一篇&#xff0c;目前該系列文章還在持續總結寫作中&#xff0c;以發表的如下&#xff0c;有興趣的可以翻閱。 [學習] RTKlib詳解&#xff1a;功能、工具與源碼結構解析 [學習]RTKLib詳解…

移植RTOS,發現任務棧溢出怎么辦?

目錄 1、硬件檢測方法 2、軟件檢測方法 3、預防堆棧溢出 4、處理堆棧溢出 在嵌入式系統中&#xff0c;RTOS通過管理多個任務來滿足嚴格的時序要求。任務堆棧管理是RTOS開發中的關鍵環節&#xff0c;尤其是在將RTOS移植到新硬件平臺時。堆棧溢出是嵌入式開發中常見的錯誤&am…

window 顯示驅動開發-使用有保證的協定 DMA 緩沖區模型

Windows Vista 的顯示驅動程序模型保證呈現設備的 DMA 緩沖區和修補程序位置列表的大小。 修補程序位置列表包含 DMA 緩沖區中命令引用的資源的物理內存地址。 在有保證的協定模式下&#xff0c;用戶模式顯示驅動程序知道 DMA 緩沖區和修補程序位置列表的確切大小&#xff0c;…

SD-HOST Controller design-----SD CLK 設計

hclk的分頻電路&#xff0c;得到的分頻時鐘作為sd卡時鐘。 該模塊最終輸出兩個時鐘&#xff1a;一個為fifo_sd_clk,另一個為out_sd_clk_dft。當不分頻時&#xff0c;fifo_sd_clk等于hclk&#xff1b;當分頻時候&#xff0c;div_counter開始計數&#xff0c;記到相應分頻的時候…

完全背包問題中「排列數」與「組合數」的核心區別

&#x1f3af; 一句話理解 求組合數&#xff08;不計順序&#xff09; → 外層遍歷物品&#xff0c;內層遍歷背包容量 求排列數&#xff08;計順序&#xff09; → 外層遍歷背包容量&#xff0c;內層遍歷物品 &#x1f3b2; 舉例說明 假設有硬幣 [1, 2, 3]&#xff0c;目標金…

NHANES指標推薦:MDS

文章題目&#xff1a;The association between magnesium depletion score (MDS) and overactive bladder (OAB) among the U.S. population DOI&#xff1a;10.1186/s41043-025-00846-x 中文標題&#xff1a;美國人群鎂耗竭評分 &#xff08;MDS&#xff09; 與膀胱過度活動癥…

C++:字符串操作函數

strcpy() 功能&#xff1a;把一個字符串復制到另一個字符串。 #include <iostream> #include <cstring> using namespace std;int main() {char src[] "Hello";char dest[10];strcpy(dest, src);cout << "Copied string: " << …

1基·2臺·3空間·6主體——藍象智聯解碼可信數據空間的“數智密碼”

近日&#xff0c;由全國數據標準化技術委員會編制的《可信數據空間 技術架構》技術文件正式發布&#xff0c;標志著我國數據要素流通體系向標準化、規范化邁出關鍵一步。該文件從技術功能、業務流程、安全要求三大維度對可信數據空間進行系統性規范&#xff0c;為地方、行業及企…

基于TI AM6442+FPGA解決方案,支持6網口,4路CAN,8個串口

TI AM6442FPGA解決方案具有以下技術優勢及適用領域&#xff1a; 一、技術優勢 ?異構多核架構?&#xff1a;AM6442處理器集成7個內核&#xff08;2xCortex-A534xCortex-R5F1xCortex-M4F&#xff09;&#xff0c;可實現應用處理、實時控制和獨立任務分核協同&#xff0c;滿足…

android vlc播放rtsp

最近在做IOT開發&#xff0c;需要把IOT設備的RTSP流在手機端播放&#xff0c;VLC是個不錯的選擇&#xff0c;使用起來簡單方便。 1、在AndroidManifest.xml 中添加網絡權限 <uses-permission android:name"android.permission.INTERNET"/> <uses-permissi…

前端面經 9 JS中的繼承

借用Class實現繼承 實現繼承 extends super extends 繼承父類 super調用父類的構造函數 子類中存在方法采取就近原則 &#xff0c;子類構造函數需要使用super()調用父類的構造函數 JS 靜態屬性和私有屬性 寄生組合式繼承

jQuery知識框架

一、jQuery 基礎 核心概念 $ 或 jQuery&#xff1a;全局函數&#xff0c;用于選擇元素或創建DOM對象。 鏈式調用&#xff1a;多數方法返回jQuery對象&#xff0c;支持連續操作。 文檔就緒事件&#xff1a; $(document).ready(function() { /* 代碼 */ }); // 簡寫 $(function…

【HCIA】BFD

前言 前面我們介紹了浮動路由以及出口路由器的默認路由配置&#xff0c;可如此配置會存在隱患&#xff0c;就是出口路由器直連的網絡設備并不是運營商的路由器&#xff0c;而是交換機。此時我們就需要感知路由器的存活狀態&#xff0c;這就需要用到 BFD&#xff08;Bidirectio…

前端流行框架Vue3教程:18. _組件數據傳遞

透傳 Attributes 透傳attribute指的是傳遞給一個組件&#xff0c;卻沒有被該組件聲明為props或emits的attribute或者v-on事件監聽器。最常見的例子就是class、style和id 當一個組件以單個元素為根作渲染時&#xff0c;透傳的attribute會自動被添加到根元素上 透傳 Attributes …

卓力達電鑄鎳網:精密制造與跨領域應用的創新典范

目錄 引言 一、電鑄鎳網的技術原理與核心特性 二、電鑄鎳網的跨領域應用 三、南通卓力達電鑄鎳網的核心優勢 四、未來技術展望 引言 電鑄鎳網作為一種兼具高精度與高性能的金屬網狀材料&#xff0c;通過電化學沉積工藝實現復雜結構的精密成型&#xff0c;已成為航空航天、電…