如何用Redis實現分布式鎖?RedLock算法的核心思想?Redisson的看門狗機制原理?

一、Redis分布式鎖基礎實現

public class RedisDistributedLock {private JedisPool jedisPool;private String lockKey;private String clientId;private int expireTime = 30; // 默認30秒public boolean tryLock() {try (Jedis jedis = jedisPool.getResource()) {// NX表示不存在時設置,PX設置過期時間(毫秒)String result = jedis.set(lockKey, clientId, SetParams.setParams().nx().px(expireTime * 1000));return "OK".equals(result);}}public void unlock() {try (Jedis jedis = jedisPool.getResource()) {// 使用Lua腳本保證原子性String script = "if redis.call('get', KEYS[1]) == ARGV[1] then " +"   return redis.call('del', KEYS[1]) " +"else " +"   return 0 " +"end";jedis.eval(script, Collections.singletonList(lockKey), Collections.singletonList(clientId));}}
}

關鍵點:

  1. 使用SET NX PX命令保證原子性
  • 單命令原子性:Redis服務器單線程順序執行命令
  • 僅包含SET操作:僅完成鍵值設置和過期時間配置
  • 無邏輯判斷:僅判斷鍵是否存在(NX特性)
  1. 客戶端唯一標識(clientId)防止誤刪
  2. Lua腳本保證解鎖操作的原子性
  • 多命令原子性:組合GET、DEL等命令的復合操作
  • 包含業務邏輯:實現"比較后刪除"的CAS(Compare And Set)操作
  • 支持復雜流程:可包含條件判斷、循環等邏輯

缺陷:
如果鎖存在A redis節點,然后B是A的從庫,服務先獲取A節點的redis key鎖,如果A網絡波動的時候的時候,主從切換,B節點升級為主節點,這個時候另一個服務獲取B節點的相同的redis key,這種情況就發生腦裂了。

二、RedLock算法核心思想

RedLock算法由Redis作者提出,主要解決單點故障問題:

  1. 多節點部署:使用5個(奇數)獨立的Redis節點
  2. 順序獲取:客戶端依次向所有節點申請鎖
  3. 成功條件:獲得超過半數的鎖(3個)
  4. 耗時計算:總耗時應小于鎖的TTL時間
  5. 失敗釋放:失敗時需要釋放所有已獲得的鎖

三、Redisson看門狗機制原理

public class RedissonWatchdogExample {public static void main(String[] args) {Config config = new Config();config.useSingleServer().setAddress("redis://127.0.0.1:6379");RedissonClient redisson = Redisson.create(config);RLock lock = redisson.getLock("myLock");try {// 默認30秒過期,看門狗自動續期lock.lock();// 業務邏輯執行時間可能超過30秒Thread.sleep(40000); } finally {lock.unlock();}}
}

集群防止腦裂

Redisson 實現分布式鎖的核心機制和集群腦裂防護原理如下:

1. 基礎鎖實現原理
-- Redis 原子操作腳本
if redis.call('exists', KEYS[1]) == 0 thenredis.call('hset', KEYS[1], ARGV[2], 1)redis.call('pexpire', KEYS[1], ARGV[1])return nil
end
2. 集群模式防護機制
// RedissonMultiLock 集群鎖實現
List<RLock> locks = new ArrayList<>();
locks.add(redissonClient1.getLock("lock1"));
locks.add(redissonClient2.getLock("lock2"));
RLock multiLock = new RedissonMultiLock(locks.toArray(new RLock[0]));

關鍵實現要點:

1. 多節點提交機制
  • 需要 N/2+1 個節點成功獲取鎖才算有效
  • 使用異步線程維持鎖心跳(Watchdog 機制)
// Watchdog 線程實現(偽代碼)
private void scheduleExpirationRenewal() {if (expirationRenewalMap.putIfAbsent(lockName, newTimeout) == null) {// 每 10 秒續期一次internalLockLeaseTime / 3 周期執行}
}
2. 腦裂防護策略
  • 同步延遲控制:主從同步超時時間 > 鎖過期時間
  • 多數派原則:成功獲取鎖的節點數 > 集群半數節點
  • 故障轉移阻斷:當節點失聯時自動啟動鎖失效倒計時
3. 異常處理機制
// 鎖釋放時的集群同步
public void unlock() {for (RLock lock : locks) {if (lock.isHeldByCurrentThread()) {lock.unlockAsync();}}
}

集群模式下重要參數配置建議:

# redisson.yaml
clusterServersConfig:nodeAddresses:- "redis://127.0.0.1:7000"- "redis://127.0.0.1:7001"scanInterval: 1000retryAttempts: 3retryInterval: 500slaveConnectionMinimumIdleSize: 8failedSlaveReconnectionInterval: 30000

該實現通過以下方式保證腦裂場景下的數據一致性:

  1. 使用 Raft 式多數派提交協議
  2. 網絡分區時自動降級為只讀模式
  3. 主節點切換后新主節點會等待舊主節點鎖超時
  4. 客戶端自動檢測集群拓撲變化并重建連接
    看門狗機制關鍵點:
  5. 后臺線程:每10秒檢查鎖狀態
  6. 自動續期:當業務未完成時,將過期時間重置為30秒
  7. 客戶端存活判斷:只有客戶端保持活躍才會續期
  8. 默認配置:lockWatchdogTimeout=30秒

四、完整方案對比

方案優點缺點
基礎Redis鎖實現簡單單點故障風險
RedLock算法高可用性實現復雜、性能損耗
Redisson實現自動續期、可重入鎖、多種鎖類型需要維護客戶端連接

實際建議:

  1. 單節點場景使用Redisson基礎鎖
  2. 高可用場景使用Redisson+Redis Cluster
  3. 極端可靠性需求使用RedLock算法

生產環境注意事項:

  1. 合理設置超時時間(業務平均耗時 * 2)
  2. 監控鎖等待時間和獲取次數
  3. 為不同業務使用不同的鎖前綴
  4. 做好鎖等待超時的異常處理

競品分析

分布式鎖實現方案對比及優劣勢分析

一、ZooKeeper 實現方案
// 使用Curator框架示例
public class ZkDistributedLock {private CuratorFramework client;private InterProcessMutex lock;public boolean tryLock(String lockPath) throws Exception {lock = new InterProcessMutex(client, lockPath);return lock.acquire(3, TimeUnit.SECONDS); // 3秒獲取超時}public void unlock() throws Exception {if (lock != null) {lock.release();}}
}

核心原理
通過創建臨時順序節點實現,獲取鎖的客戶端會生成有序節點,只有序號最小的節點持有鎖

優勢

  1. 自動釋放(會話失效時自動刪除節點)
  2. 公平鎖機制(順序節點)
  3. 強一致性保證

劣勢

  1. 寫操作性能低于Redis
  2. 需要維護ZooKeeper集群
  3. 客戶端實現相對復雜

二、Etcd 實現方案
// 使用jetcd客戶端示例
public class EtcdDistributedLock {private Client client;private Lease lease;public boolean tryLock(String lockKey) throws Exception {lease = client.getLeaseClient().grant(30).get(); // 30秒租約Txn txn = client.getKVClient().txn();txn.If(new Cmp(lockKey, Cmp.Op.EQUAL, CmpTarget.version(0))).Then(Op.put(lockKey, "locked", PutOption.newBuilder().withLeaseId(lease.getID()).build())).Else(Op.get(lockKey));return txn.commit().get().isSucceeded();}
}

核心原理
基于租約(Lease)機制,利用事務操作實現原子性鎖獲取

優勢

  1. 強一致性(Raft協議)
  2. 自動續期機制
  3. 支持公平鎖/非公平鎖

劣勢

  1. 運維復雜度較高
  2. 客戶端生態不如Redis完善
  3. 性能低于Redis

三、數據庫實現方案
// 基于MySQL的樂觀鎖實現
public class DbDistributedLock {@Transactionalpublic boolean tryLock(String lockName) {// 使用唯一索引約束int result = jdbcTemplate.update("INSERT INTO distributed_lock(lock_name,owner) VALUES (?,?) ON DUPLICATE KEY UPDATE owner=IF(expire_time < NOW(), VALUES(owner), owner)",lockName, UUID.randomUUID().toString());return result > 0;}
}

核心原理
基于數據庫唯一約束或排他鎖(SELECT FOR UPDATE)

優勢

  1. 無需額外中間件
  2. 實現簡單快速

劣勢

  1. 性能差(高并發場景容易成為瓶頸)
  2. 無自動釋放機制
  3. 死鎖風險較高

方案對比總結表

方案一致性性能自動釋放實現復雜度適用場景
Redis最終一致支持簡單高并發、允許短暫不一致
ZooKeeper強一致支持復雜強一致性要求、公平鎖場景
Etcd強一致支持較復雜強一致性且需要自動續期
數據庫強一致不支持簡單低頻訪問、無中間件環境的應急方案

選型建議

  1. 追求性能 ? Redis(Redisson實現)
  2. 強一致性要求 ? ZooKeeper/Etcd
  3. 無中間件環境 ? 數據庫方案(需謹慎處理超時)
  4. 混合使用場景 ? 可組合使用(如Redis做主鎖,數據庫做備用鎖)

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

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

相關文章

前端面試寶典---js垃圾回收機制

什么是垃圾回收 垃圾回收是指一種自動內存管理機制&#xff0c;當聲明一個變量時&#xff0c;會在內存中開辟一塊內存空間用于存放這個變量。當這個變量被使用過后&#xff0c;可能再也不需要它了&#xff0c;此時垃圾回收器會自動檢測并回收這些不再使用的內存空間。垃圾回收…

阿里媽媽LMA2新進展:集成大語言模型與電商知識的通用召回大模型URM

近日&#xff0c;阿里媽媽在國際頂級學術會議 —— 國際萬維網大會&#xff08;International World Wide Web Conference, 簡稱WWW&#xff09;上共同主持了計算廣告算法技術相關的Tutorial&#xff08;講座&#xff09;&#xff0c;介紹了計算廣告領域的技術發展脈絡&#xf…

數字孿生實時監控汽車零部件工廠智能化巡檢新范式

在汽車制造業面臨數字化轉型時&#xff0c;汽車零部件工廠也面臨著提升生產效率、降低運營成本和增強市場競爭力的多重挑戰。傳統的巡檢方式已經難以滿足現代工廠對高效、精準管理和實時決策的需求。數字孿生系統的出現&#xff0c;為汽車零部件工廠提供了一種創新的智能化巡檢…

【計算機網絡】3數據鏈路層②

1. 數據鏈路層所處的地位 數據鏈路層使用的信道主要有兩種: ①點對點信道:PPP協議 ②廣播信道:有線局域網,CSMA/CD協議;無線局域網,CSMA/CA協議 對比項點對點信道 vs 單播廣播信道 vs 廣播核心是否一致? 一致(一對一傳輸)? 一致(一對所有傳輸)差異點前者是物理層…

c++中的函數(默認參數,占位參數,重載)

1&#xff0c;函數默認參數 在c中&#xff0c;函數的形參列表中的形參是可以有默認值得 語法&#xff1a;返回值類型 函數名 &#xff08;參數 默認值&#xff09;{} 示例&#xff1a; #include<iostream> using namespace std;//函數默認參數 // 就是如果傳了就…

【原創】使用阿里云存放一個臨時共享的文件

在某些場合&#xff0c;需要臨時將一個文件存儲到一個可被公網訪問的地方&#xff0c;某個服務需要訪問一下這個文件。這個文件基本上就是一次壽命&#xff0c;也就是你上傳一下&#xff0c;然后被訪問一下&#xff0c;這個文件的壽命就結束了。 對于這種需求&#xff0c;自建…

Python中列表(list)知識詳解(2)和注意事項以及應用示例

在 Python 中列表&#xff08;list&#xff09; 的包括其結構、常見操作&#xff08;更新、添加、刪除、查找、隊列棧行為等&#xff09;&#xff0c;下面將逐一的進行講解并附相關的示例。 一、列表的基礎知識 1. 定義與特點 定義方式&#xff1a;用 [] 包裹的有序可變集合 …

vscode extention踩坑記

# npx vsce package --allow-missing-repository --no-dependencies #耗時且不穩定 npx vsce package --allow-missing-repository #用這行 code --install-extension $vsixFileName --force我問ai&#xff1a;為什么我的.vsix文件大了那么多 ai答&#xff1a;因為你沒有用 --n…

移動端巡檢點檢,讓設備管理更便捷高效

在企業設備管理的日常工作中&#xff0c;巡檢點檢是保障設備正常運行的重要環節。傳統的巡檢方式依賴紙質記錄、人工操作&#xff0c;效率低、易出錯&#xff0c;已難以滿足現代企業的管理需求。隨著技術發展&#xff0c;越來越多設備管理系統引入移動端功能&#xff0c;為設備…

laravel 中使用的pdf 擴展包 laravel-snappy(已解決中文亂碼)

Centos7 安裝 wkhtmltopdf 1、先查看系統是 32 位的還是 64 位的 uname -a2、通過 composer 安裝 wkhtmltopdf 32位: $ composer require h4cc / wkhtmltopdf-i386 0.12.x $ composer require h4cc / wkhtmltoimage-i386 0.12.x 64位: $ composer require h4cc/wkhtmltopdf-…

Rust:重新定義系統編程的安全與效率邊界

在軟件工程領域&#xff0c;內存安全漏洞每年造成數千億美元損失&#xff0c;而C/C生態中60%的漏洞源于指針誤用。正是在這樣的背景下&#xff0c;Rust憑借其革命性的內存安全機制異軍突起。作為一門現代系統級編程語言&#xff0c;Rust不僅解決了困擾開發者數十年的內存管理難…

C++學習細節回顧(匯總二)

一.初始化列表相關 1.初始化順序受申明順序影響 2.在必要時可以部分不采用初始化列表&#xff0c;避免受特性1影響 二.非類型模板參數 template< class T , size_t N 10 > 三.特化–特殊化處理 template< class T > bool less(T left , T right) { return left&…

勾選某一行的勾選框,更改當前行的顏色,ALV數據發生變化的事件

文章目錄 屏幕ALV的創建定義變量注冊事件方法定義方法實現frm_data_change 效果 屏幕 ALV的創建 DATA: g_gui_custom_container TYPE REF TO cl_gui_custom_container. DATA: g_gui_alv_grid TYPE REF TO cl_gui_alv_grid.DATA: gt_listheader TYPE slis_t_listheader, &quo…

AI-02a5a6.神經網絡-與學習相關的技巧-批量歸一化

批量歸一化 Batch Normalization 設置合適的權重初始值&#xff0c;則各層的激活值分布會有適當的廣度&#xff0c;從而可以順利的進行學習。那么&#xff0c;更進一步&#xff0c;強制性的調整激活值的分布&#xff0c;是的各層擁有適當的廣度呢&#xff1f;批量歸一化&#…

解決SQL Server SQL語句性能問題(9)——合理使用表分區

9.2. 合理使用表分區 本專欄4.1.4節中,我們對表分區相關的概念和機制等基礎理論進行了較為詳細的介紹和論述,讀者可以參考該節中內容,或者,讀者也可以參考官方或其他相關資料。與其他關系庫類似,SQL Server 2005版本中引進的真正意義上的表分區技術,絕對是解決海量數據環…

C語言學習之文件操作

經過前面的學習&#xff0c;我們已經基本掌握了如何去寫一個C語言的代碼了。但是在實際的項目中&#xff0c;我們不可能不需要文件去操作。因為如果沒有文件&#xff0c;我們寫的程序是存儲在電腦的內存中的。如果程序推出&#xff0c;內存回收數據就隨之丟失了。如果我們要對數…

2025年PMP 學習十三 第9章 項目資源管理(9.1,9.2)

2025年PMP 學習十三 第9章 項目資源管理&#xff08;9.1,9.2&#xff09; 序號過程過程組9.1規劃資源管理規劃9.2估算活動資源規劃9.3獲取資源執行9.4建設團隊執行9.5管理團隊執行9.6控制資源監控 文章目錄 2025年PMP 學習十三 第9章 項目資源管理&#xff08;9.1,9.2&#xf…

藍橋杯13屆國B 完全日期

題目描述。 如果一個日期中年月日的各位數字之和是完全平方數&#xff0c;則稱為一個完全日期。 例如&#xff1a;2021 年 6 月 5 日的各位數字之和為 20216516&#xff0c;而 16 是一個完全平方數&#xff0c;它是 4 的平方。所以 2021 年 6 月 5 日是一個完全日期。 例如&…

某某霸翻譯逆向分析[JS逆向]

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

開源Heygem本地跑AI數字人視頻教程

圖文教程&#xff1a; 點擊跳轉 視頻教程 資料包下載 點擊下載&#xff1a;