Redisson 實現分布式鎖源碼淺析

大家好,我是此林。

今天來分享Redisson分布式鎖源碼。還是一樣,我們用?問題驅動?的方式展開講述。

1. redis 中如何使用 lua 腳本?

Redis內置了lua解釋器,lua腳本有兩個好處:

1. 減少多次Redis命令的網絡傳輸開銷。(當然也可以使用pipline命令)

2. lua腳本所有命令能保證原子性,隔離性(Redis單線程),失敗回滾

綜上所述,Redis中如果想要實現事務操作,可以使用lua腳本。

Redis 本身也可以使用 MULTI + WATCH樂觀鎖?來實現,但是它只能保證命令執行的順序性,無法保證失敗回滾,無法保證原子性。

所以,一般推薦使用 lua 腳本。

使用案例:

現在我們要去執行redis命令:

HSET info name john 

1. lua腳本

local hash_key = KEYS[1]    -- 哈希結構的鍵名(外部傳入)
local key = ARGV[1]         -- 哈希字段(外部傳入)
local value = ARGV[2]       -- 哈希字段值(外部傳入)return redis.call('HSET', hash_key, key, value)

因為KEYS[1]、ARGV[1]等都是外部傳入,所以可以簡化。

return redis.call('HSET', KEYS[1], ARGV[1], ARGV[2])

redis.call()就是執行redis命令。

2. redis 命令

EVAL "return redis.call('HSET', KEYS[1], ARGV[1], ARGV[2])" 1 info name john

這里的1代表傳入一個key。

2. 如何使用Redisson?

這里的?

boolean isLock = lock.tryLock(1, 10, TimeUnit.SECONDS);

是獲取鎖,第一個1表示:鎖超時等待時間,在1秒內會不斷重試獲取鎖,直到獲取到。

第二個10表示:鎖釋放時間,為10秒(防止java服務獲取到鎖后,突然宕機,導致redis鎖永遠不會被釋放,避免造成死鎖問題。)

3. Redisson源碼?

3.1. Redisson如何實現鎖重入?

其實歸根結底,就是這段代碼。Redisson本質上是使用hash結構來標志鎖的,可能我們經常聽到說用setnx命令來實現分布式鎖,但是setnx無法實現鎖的重入。

所以Redisson用 hash(計數) + lua腳本(原子性)實現可重入分布式鎖。

先說明下參數:

KEYS[1]:hash結構的鍵名,也就是我們之前手動指定的 anylock

ARGV[1]:鎖的釋放時間

ARGV[2]:hash結構的字段的鍵名,UUID:線程id

我們直接去看redis:

anyLock這個hash結構里,

有字段的key為c3341b71-6edd-4db8-b626-9135cf727fd4:1,value為1

了解了鎖的結構后,我們再來看lua腳本。

一圖勝千言,總的來說,

第一個if:處理線程第一次獲取鎖

第二個if:處理線程重入獲取鎖

最后:發現鎖已經被占有,返回剩余ttl(過期時間)。



3.2. 如果搶鎖失敗呢?

之前說的鎖的設置,其實就是圖中框起來的方法里的實現。

接下來,如果ttl為null,搶鎖成功了,直接返回true。

如果ttl不為null,說明搶鎖失敗了,會去計算等待時間是否充足。

這里的等待時間就是我們之前手動設置的1秒鐘。

如果鎖等待時間還充足,那么執行它會去用pub-sub機制去?訂閱鎖釋放事件。(避免輪詢 Redis 造成的性能損耗。

如果訂閱超時,觸發失敗回調,返回false。?

那么訂閱成功了之后呢?會再次嘗試搶鎖。

還不行,那只能信號量掛起,具體通過?SemaphoregetLatch())掛起當前線程,等待鎖釋放的 Pub/Sub 通知。?

總結一下搶鎖流程:

搶鎖成功,直接返回;搶鎖失敗,pub/sub機制訂閱鎖釋放事件,通過信號量掛起線程,直到收到鎖釋放的消息才被喚醒。

3.3. 解鎖流程是怎么樣的?

看下圖。本質還是那一段lua腳本。

先看下鎖是不是線程自己的,不是的話直接返回null。

如果鎖是自己的,計數器減1。

如果減1操作后還大于0,說明重入的還沒完,刷新鎖的超時釋放時間。

如果減1后小于等于0,直接刪除,發布鎖刪除事件。

  • 返回nil表示鎖不屬于當前線程,應拋出異常。
  • 返回0表示鎖未完全釋放,僅更新了過期時間。
  • 返回1表示鎖已釋放,并發布事件。

3.4. Redisson的看門狗機制?

看門狗主要用于 ?解決鎖的自動續期問題,避免因業務執行時間過長導致鎖超時自動釋放。

注意一點:如果我們顯式指定了leaseTime參數,看門狗機制就不會生效。這時候鎖的過期時間由用戶控制。

像我們之前手動指定了鎖釋放時間10秒,它就不會走看門狗機制,Redisson默認鎖釋放時間是30秒。(見下圖,單位毫秒)

在scheduledExpirationRenewal方法里,其實就是用了netty的時間輪進行定時任務調度,每隔10秒重置鎖時間為30秒,直到業務執行結束。

每次續期成功后,會遞歸調用?renewExpiration(),形成 ?無限續期鏈,直到鎖被釋放(主動釋放或者客戶端宕機)。

關于??時間輪,這是一種高效的定時任務調度設計

感興趣的朋友可以去看下之前寫的文章:

時間輪:XXL-JOB 高效、精準定時任務調度實現思路分析_xxljob fasttriggerpool slowtrigger-CSDN博客

至于為什么不使用ScheduledThreadPoolExecutor?

是因為ScheduledThreadPoolExecutor的底層結構:基于優先級隊列(堆實現)。插入任務的時間復雜度?O(log n),每次插入需調整堆結構。

使用時間輪插入任務的時間復雜度為?O(1),直接哈希到時間槽(Bucket),并且支持同一槽內任務批量觸發。

3.5. Redisson怎么解決死鎖的?

主要就是設置了鎖的超時釋放時間,客戶端宕機了會自動超時釋放。

然后還有一點支持重入,如果同一個線程兩次去獲取鎖,因為支持重入,第二次就不會阻塞等待自己釋放鎖了。

至于說看門狗機制會無限續期,客戶端宕機了就續期不了,不會導致死鎖。

那你說:業務要是無限阻塞,永遠執行不完呢?

這個也不大可能,為什么業務會無限阻塞?這個時候肯定需要人工介入去排查問題了。

今天的分享就到這里了,我是此林。

關注我吧,帶你看不一樣的世界!

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

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

相關文章

【軟件】免費的PDF全文翻譯軟件,能保留公式圖表的樣式

轉載請注明出處:小鋒學長生活大爆炸[xfxuezhagn.cn] 如果本文幫助到了你,歡迎[點贊、收藏、關注]哦~ 很多PDF全文翻譯軟件都是收費的,而劃線翻譯看著又很累。這個開源的PDF全文翻譯軟件非常好用,并且能夠保留公式、圖表、目錄和注…

CentOS 7 系統上安裝 SQLite

1. 檢查系統更新 在安裝新軟件之前,建議先更新系統的軟件包列表,以確保使用的是最新的軟件源和補丁。打開終端,執行以下命令: sudo yum update -y -y 選項表示在更新過程中自動回答 “yes”,避免手動確認。 2. 安裝 …

Gin(后端)和 Vue3(前端)中實現 Server-Sent Events(SSE)推送

在 Gin(后端)和 Vue3(前端)中實現 Server-Sent Events(SSE)推送,主要分為以下幾個步驟: 后端(Gin)實現 SSE Gin 框架可以使用 c.SSEvent 方法來推送 SSE 事…

大模型微調中顯存占用和訓練時間的影響因素

BatchSize 顯存占用:與batch_size呈線性關系,可理解為 M t o t a l M f i x e d B a t c h S i z e ? M p e r ? s a m p l e M_{total}M_{fixed}BatchSize*M_{per-sample} Mtotal?Mfixed?BatchSize?Mper?sample?,其中 M f i x e d…

【排序算法對比】快速排序、歸并排序、堆排序

排序算法對比:快速排序、歸并排序、堆排序 1. 快速排序(Quick Sort) 原理 快速排序采用 分治法(Divide and Conquer),通過選取基準值(pivot),將數組劃分為 小于基準值…

PentestGPT 下載

PentestGPT 下載 PentestGPT 介紹 PentestGPT(Penetration Testing GPT)是一個基于大語言模型(LLM)的智能滲透測試助手。它結合了 ChatGPT(或其他 GPT 模型)與滲透測試工具,幫助安全研究人員自…

防火墻虛擬系統實驗

一實驗拓撲 二實驗過程 配置資源 創建虛擬系統 配置管理員 創建安全策略

代碼隨想錄算法訓練營第31天 | 56. 合并區間 738.單調遞增的數字 968.監控二叉樹

56. 合并區間 代碼隨想錄 56. 合并區間 - 力扣&#xff08;LeetCode&#xff09; class Solution {public int[][] merge(int[][] intervals) {Arrays.sort(intervals,(a,b)->{if(a[0] b[0])return a[1] - b[1];return a[0] - b[0];});List<int[]> result new Arra…

Go語言對于MySQL的基本操作

一.下載依賴 終端中輸入&#xff1a; go get -u github.com/go-sql-driver/mysql 導入包 import ("database/sql"_ "github.com/go-sql-driver/mysql" ) 二.案例 package main//go get-u github.com/go-sql-driver/mysql 獲取驅動 import ("databa…

Linux與深入HTTP序列化和反序列化

深入HTTP序列化和反序列化 本篇介紹 在上一節已經完成了客戶端和服務端基本的HTTP通信&#xff0c;但是前面的傳遞并沒有完全體現出HTTP的序列化和反序列化&#xff0c;為了更好得理解其工作流程&#xff0c;在本節會以更加具體的方式分析到HTTP序列化和反序列化 本節會在介紹…

基于Python+SQLite實現(Web)驗室設備管理系統

實驗室設備管理系統 應用背景 為方便實驗室進行設備管理&#xff0c;某大學擬開發實驗室設備管理系統 來管理所有實驗室里的各種設備。系統可實現管理員登錄&#xff0c;查看現有的所有設備&#xff0c; 增加設備等功能。 開發環境 Mac OSPyCharm IDEPython3Flask&#xff…

深拷貝and淺拷貝!

一、什么是拷貝&#xff1f;什么是深拷貝和淺拷貝&#xff1f; &#xff08;1&#xff09;拷貝&#xff1a;拷貝就是為了復用原對象的部分or全部數據&#xff0c;在原對象的基礎上通過復制的方式創建一個新的對象。 拷貝對象可以分為三種類型&#xff1a;直接賦值、淺拷貝和深拷…

高頻面試題(含筆試高頻算法整理)基本總結回顧43

干貨分享&#xff0c;感謝您的閱讀&#xff01; &#xff08;暫存篇---后續會刪除&#xff0c;完整版和持續更新見高頻面試題基本總結回顧&#xff08;含筆試高頻算法整理&#xff09;&#xff09; 備注&#xff1a;引用請標注出處&#xff0c;同時存在的問題請在相關博客留言…

《靈珠覺醒:從零到算法金仙的C++修煉》卷三·天劫試煉(34)混元金斗裝萬物 - 0-1背包問題(二維DP)

《靈珠覺醒:從零到算法金仙的C++修煉》卷三天劫試煉(34)混元金斗裝萬物 - 0-1背包問題(二維DP) 哪吒在數據修仙界中繼續他的修煉之旅。這一次,他來到了一片神秘的混元谷,谷中有一座巨大的混元金斗,斗身閃爍著神秘的光芒。谷口有一塊巨大的石碑,上面刻著一行文字:“欲…

網絡爬蟲【簡介】

我叫補三補四&#xff0c;很高興見到大家&#xff0c;歡迎一起學習交流和進步 今天來講一講視圖 一、網絡爬蟲的定義 網絡爬蟲&#xff08;Web Crawler&#xff09;&#xff0c;又稱為網絡蜘蛛、網絡機器人等&#xff0c;是一種按照一定規則自動抓取互聯網信息的程序或腳本。它…

?AI時代到來,對電商來說是效率躍升,還是溫水煮青蛙

?凌晨三點的義烏商貿城&#xff0c;95后創業者小王&#xff0c;靜靜地盯著屏幕上的AI工具&#xff0c;竟露出了笑容。這個月他的跨境玩具店銷量提升了不少&#xff0c;從之前的狀態翻了3倍&#xff1b;而且團隊人數有所變化&#xff0c;從5人縮減到了2人&#xff08;其中包括他…

PDF文件密碼保護破解:安全解密的步驟與技巧

PDF文件加密后&#xff0c;需要特定的密碼才能訪問內容。以下是一些常見的方法來解密PDF文件&#xff1a; 方法一&#xff1a;使用Adobe Acrobat 如果你有Adobe Acrobat Pro&#xff0c;可以使用它來解密PDF文件。 打開Adobe Acrobat Pro&#xff1a; 啟動Adobe Acrobat Pro…

qt 自帶虛擬鍵盤的編譯使用記錄

一、windows 下編譯 使用vs 命令窗口&#xff0c;分別執行&#xff1a; qmake CONFIG"lang-en_GB lang-zh_CN" nmake nmake install 如果事先沒有 指定需要使用的輸入法語言就進行過編譯&#xff0c;則需要先 執行 nmake distclean 清理后執行 qmake 才能生效。 …

Java開發之數據庫應用:記一次醫療系統數據庫遷移引發的異常:從MySQL到PostgreSQL的“dual“表陷阱與突圍之路

記一次醫療系統數據庫遷移引發的異常&#xff1a;從MySQL到PostgreSQL的"dual"表陷阱與突圍之路 一、驚魂時刻&#xff1a;數據庫切換引發的系統雪崩 某醫療影像系統在進行國產化改造過程中&#xff0c;將原MySQL數據庫遷移至PostgreSQL。遷移完成后&#xff0c;系…

C++刷題(二):棧 + 隊列

&#x1f4dd;前言說明&#xff1a; 本專欄主要記錄本人的基礎算法學習以及刷題記錄&#xff0c;使用語言為C。 每道題我會給出LeetCode上的題號&#xff08;如果有題號&#xff09;&#xff0c;題目&#xff0c;以及最后通過的代碼。沒有題號的題目大多來自牛客網。對于題目的…