Redis原理之分布式鎖

上篇文章:

Redis原理之緩存https://blog.csdn.net/sniper_fandc/article/details/149141968?fromshare=blogdetail&sharetype=blogdetail&sharerId=149141968&sharerefer=PC&sharesource=sniper_fandc&sharefrom=from_link???????

目錄

1 基本實現

2 引入過期時間

3 引入校驗id

4 引入lua腳本

5 引入看門狗機制(watch dog)

6 引入Redlock算法


????????普通的鎖比如Java中的synchronized通常解決的是線程安全問題,但是到了多進程多服務器環境下,普通的鎖就無法保證多個進程或節點同時訪問同一個資源的問題,這就需要分布式鎖。

????????分布式鎖從本質來講是通過一個公共服務器來記錄加鎖狀態。所有的進程或節點訪問某個資源時先訪問該服務器嘗試加鎖,待某個已經加鎖的進程或節點訪問結束后再解鎖讓其他進程或節點訪問。

????????注意:個人理解的分布式鎖核心問題是進程間通信問題。分布式環境下,進程間通過網絡通信,網絡IO的時間是各種數據IO方式中最慢的(寄存器>緩存>內存>磁盤>網絡),因此進程對一個數據進行訪問就有了時延。而在這個時延期間,如果有其他進程也對該數據進行訪問(失去了原子性),就可能造成數據不一致或重復讀寫等問題,因此需要通過鎖來控制進程通信的順序問題(互斥性)。

1 基本實現

????????注意:實現分布式鎖可以有很多方式,比如Redis、MySQL和ZooKeeper等等。

????????這里使用Redis來實現分布式鎖。核心操作是當多個客戶端進程查詢同一個資源時,請求負載均衡到某個服務器后首先訪問Redis,第一個進程會在Redis設置關于該資源的key-value(加鎖)。此時其他進程(服務器)如果也想查詢該資源就會去Redis嘗試加鎖,如果發現key已經存在就加鎖失敗,可以選擇阻塞或返回(具體哪種看實現場景)。待第一個進程訪問資源結束后,就會把Redis上的這個key-value刪除(解鎖)。

????????使用setnx命令即可實現這個分布式鎖:key不存在則設置(加鎖),否則失敗(加鎖失敗)。使用del命令即可實現解鎖。

2 引入過期時間

????????當在Redis加鎖的服務器如果出現意外情況,比如宕機、斷電等等,鎖還未釋放,此時其它服務器就無法對該資源加鎖,從而無法訪問資源。

????????解決辦法:對key-value引入過期時間,即使用set ex nx命令來設置過期時間。

????????注意:不能使用setnx、expire兩條命令來實現上述效果,因為Redis的命令是串行化執行的,無法保證多條命令執行的原子性。

3 引入校驗id

????????上述方案還有問題,由于多個服務器都可以訪問Redis來執行各種命令,就可能出現一個服務器設置鍵值對(加鎖),另一個服務器刪除鍵值對(解鎖),從而導致問題(當然這個問題不是故意的)。

????????解決辦法:為每個服務器引入校驗id,加鎖時針對某個資源的key的value設置為服務器的校驗id值。當解鎖時,首先查詢準備執行del命令的服務器的校驗id是否和value值相同,如果相同則允許執行del;如果不同則不允許執行。上述過程由服務器來完成:

String key = [要加鎖的資源id];String serverId = [服務器的id];// 加鎖, 設置過期時間為 10sredis.set(key, serverId, "NX", "EX", "10s");// 執行各種業務邏輯, 比如修改數據庫數據.doSomeThing();// 解鎖, 刪除 key. 但是刪除前要檢驗下serverId是否匹配.if (redis.get(key) == serverId) {redis.del(key);}

4 引入lua腳本

????????新的問題又出現了,執行解鎖的過程中,由于get命令和del命令的執行不是原子性的,因此就會出現命令插隊的情況。比如同一個服務器多個線程都需要操作同一個資源,當執行解鎖時按照如下所示順序執行:

????????在線程2執行完get判斷鎖的校驗id和服務器id一樣后,線程1繼續執行del已經解鎖了。而此時服務器2判斷該資源是無鎖狀態就加鎖,此時線程2又執行del把剛加的鎖給解除了,從而引起問題。

????????解決辦法:保證解鎖時兩個命令執行的原子性。可以用redis事務來解決,但是更好的方案是lua腳本。Lua是Redis的內嵌腳本語言,Lua腳本的執行是原子性的:

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

????????KEYS和ARGV是調用腳本時輸入的參數。上述代碼存于.lua后綴的文件,并發送給Redis服務器來執行。

5 引入看門狗機制(watch dog)

????????從引入過期時間開始就一直存留一個問題:過期時間設多長合適?過短的時間可能服務器還沒有訪問完資源鎖就被釋放了;過長的時間可能服務器早已經結束資源訪問但是鎖遲遲無法釋放(影響系統并發量和吞吐量)。

????????解決辦法:動態調整過期時間,初始設置一個時間,待時間快結束時(定期)查詢服務器是否訪問資源結束,如果未結束則延長時間(續約,重新設置過期時間);如果已經結束則通過lua腳本解鎖。這個動態調整過期時間的過程由服務器的一個線程專門負責,該線程也被成為看門狗,因此這個機制就被稱為看門狗機制

????????上述過程,如果服務器宕機,看門狗線程也就掛了,此時key的過期時間無人續約,也就快速解鎖便于讓其它服務器進程能及時訪問資源。

6 引入Redlock算法

????????通常Redis節點的部署不是單機形式,至少是主從復制。主從復制存在從節點和主節點短時間的數據不一致,假設向master進行加鎖操作,master還未及時同步給slave就故障,此時其它服務器也就可以進行加鎖操作。

????????解決辦法:引入Redlock算法,具體而言,加鎖時不是向一個master節點寫入,而是向所有的master節點都加鎖。如果超過超時時間仍未加鎖成功,則認為對該master加鎖失敗(該節點可能宕機)。當向所有master都嘗試加鎖后,統計加鎖成功的節點數超過半數master節點數,則認為加鎖成功。通過這樣,即使有master節點掛了,其它master節點仍然保存著鎖的信息。

????????解鎖時,也要向所有的master節點嘗試解鎖。即Redlock算法的核心思想就是冗余備份,同時結合分布式的少數服從多數的思想。

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

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

相關文章

網絡基礎19:OSPF單區域原理實驗

一、實驗拓撲二、設備配置AR1 配置<AR1> system-view [AR1] interface GigabitEthernet0/0/0 [AR1-GigabitEthernet0/0/0] ip address 192.168.1.1 24 [AR1-GigabitEthernet0/0/0] quit[AR1] ospf 1 router-id 0.0.0.1 [AR1-ospf-1] area 0 [AR1-ospf-1-area-0.0.0.0] ne…

【實戰推薦】小白也能上手的多端陪玩系統平臺項目源碼

在當今的游戲市場中&#xff0c;游戲陪玩服務已經成為了一個熱門領域。無論是尋找高手帶自己升級、學習游戲技巧&#xff0c;還是僅僅想找人一起玩耍&#xff0c;越來越多的玩家傾向于通過專業的陪玩平臺找到合適的伙伴。對于想要進入這個市場的創業者和開發者來說&#xff0c;…

[hot 100 ]最長連續序列-Python3

需要時間復雜度為O(n)&#xff0c;如果采用暴力求解則為O(n^2)1.在遍歷hash表的時候檢查是否當前值為連續序列的最小值,如果是&#xff0c;則跳過此次循環,這樣使得原本需要對每個值進行一次遍歷變成了對每個值只訪問一次:2.使用set()和普通for num in nums的區別&#xff1a;

[element-plus] el-table show-overflow-tooltip 沒有顯示省略號

<el-table-columnprop"col2"label"列2"width"70"show-overflow-tooltip/> </el-table-column>不知道為什么沒有省略號 再給加個樣式 <el-table-column prop"col2" label"列2" width"70" show-ove…

網絡基礎19--OSPF路由協議單區域

一. RIP的不足跳數評估非最優路徑&#xff1a;RIP以跳數作為度量值&#xff0c;不考慮帶寬&#xff0c;可能導致次優路徑選擇。網絡規模限制&#xff1a;最大跳數為16&#xff0c;限制了網絡規模。收斂速度慢&#xff1a;更新周期長&#xff08;默認30秒&#xff09;&#xff0…

SpringBoot 整合 Langchain4j 實現會話記憶存儲深度解析

目錄 一、前言 二、AI大模型會話記憶介紹 2.1 AI 大模型的會話記憶是什么 2.2 AI 大模型為什么需要會話記憶 2.3 AI 大模型會話記憶常用實現方案 2.4 LangChain4j 會話記憶介紹 2.4.1 LangChain4j 會話記憶介紹 2.4.2 LangChain4j 會話記憶類型 三、Langchain4j 會話記…

《R 矩陣》

《R 矩陣》 引言 在數學與統計學領域&#xff0c;矩陣是一種強大的工具&#xff0c;它廣泛應用于各種科學研究和實際應用中。本文將深入探討 R 矩陣的概念、特性及其在數據分析中的應用。 R 矩陣的定義與特性 1. 定義 R 矩陣&#xff0c;全稱為“實對稱矩陣”&#xff0c;是指一…

從java到vue3:第二天

文章目錄前言一、setup1.定義2.作用3.響應式數據1.ref2.reactive3.ref與reactive的區別4.toRefs5.computed二、Watch1.監視ref&#xff1a;基本數據2.監視ref&#xff1a;對象數據3.監視reactive&#xff1a;對象數據。4.監視ref或reactive中某個屬性5.監視多個屬性總結前言 s…

基于 JmsClient 的高效消息通信架構設計與實現

1. 引言 1.1 消息通信在分布式系統中的作用 隨著企業級應用的復雜性不斷提升,傳統的同步調用方式已難以滿足高并發、低延遲、高可用等需求。消息通信機制通過異步解耦的方式,提升了系統的可擴展性和容錯能力。Java Message Service(JMS)作為一種標準的消息中間件接口,廣…

2025.7.24

這題寫了好一會, 因為遇到一些問題分糖分的是原來的糖果還是拿到了別人給的糖果加起來一起的?如果是分原來的糖果之后那就要再另外那一個數組存, 數組初始為0, 那么分完之后自己的那一份應該存進另一個數組, 是加法如果是分拿到了別人給的糖果加起來一起的, 那么分完之后不是直…

學習設計模式《十九》——享元模式

一、基礎概念 享元模式的本質是【分離與共享】。 思考享元模式序號說明1 【分離】的是對象狀態中變與不變的部分&#xff0c;【共享】的是對象中不變的部分&#xff1b; 享元模式的關鍵就在于【分離變與不變】把不變的部分作為享元對象的內部狀態&#xff0c;而變化部分則作為外…

AI助力 三步實現電子發票發票號碼的提取

小伙伴們&#xff0c;大家好今天我們來利用ollama本地大模型&#xff0c;三步實現電子發票發票號碼的提取。 步驟1&#xff1a;安裝Ollama訪問官網https://ollama.com/ 下載相應的版本進行安裝&#xff0c;下載屬于自己平臺的ollama&#xff0c;根據安裝向導完成安裝。…

告別下載中斷:深入解析Tomcat JSP中的“遠程主機強迫關閉連接”與“軟件中止連接”

在Web開發中,提供文件下載功能是一項常見需求。然而,當用戶在Tomcat JSP項目中嘗試下載文件時,有時會遭遇令人頭疼的錯誤提示:“遠程主機強迫關閉了一個現有鏈接”(Remote host closed connection unexpectedly)或“您的主機中的軟件中止了一個已建立的連接”(Software …

實戰演練—基于Transformers的NLP解決方案總結

實戰演練—基于Transformers的NLP解決方案總結 截至目前講解的基礎組件 以文本分類為例 Transformers顯存優化 截至目前講解的基礎組件 Pipeline 流水線,用于模型推理,封裝了完整的推理邏輯,包括數據預處理、模型預測及后處理 Tokenizer 分詞器,用于數據預處理,將原始文本…

Java 解析前端上傳 ZIP 壓縮包內 Excel 文件的完整實現方案

使用zip壓縮包上傳excel文件的優點1、體積更小&#xff0c;節約帶寬2、比excel直接讀取更方便攜帶參數及修改3、可以一次性批量導入Java代碼 ControllerPostMapping("/importData")ApiOperationSupport(order 3)ApiOperation(value "上傳")public R impo…

【shell腳本編程】day1 備份指定文件類型

文章目錄1、腳本要求2、腳本編寫3、腳本解釋4、腳本改進1、腳本要求 編寫一個腳本&#xff0c;遍歷/data/目錄下的.txt文件將這些txt文件做一個備份備份的文件名增加一個年月日的后綴&#xff0c;比如將aming.txt備份為aming.txt_20231001 2、腳本編寫 [rootlocalhost shell…

Gata 攜手 Walrus 構建 AI 的開放執行基礎設施

致力于開發去中心化大模型推理、訓練和數據技術的 Gata&#xff0c;現已整合 Walrus&#xff0c;作為其 AI 開放執行基礎設施的核心組件。Walrus 將為 Gata 的首款產品 DataAgent 提供關鍵的數據層&#xff0c;助力其全套應用&#xff0c;將去中心化 AI 的優勢直接帶給用戶&…

DNS及DNS域名解析流程

文章目錄什么是DNS域名解析DNS服務器DNS域名解析流程什么是DNS域名解析 我們首先要了解域名和IP地址的區別。IP地址是互聯網上計算機唯一的邏輯地址&#xff0c;通過IP地址實現不同計算機之間的相互通信&#xff0c;每臺聯網計算機都需要通過IP地址來互相聯系和分別。 但由于I…

用 STM32 的 SYSTICK 定時器與端口復用重映射玩轉嵌入式開發

目錄 1. SYSTICK 定時器的基本功:時間管理大師 1.1 SYSTICK 的核心寄存器與工作原理 1.2 配置 SYSTICK 的正確姿勢 1.3 實戰:用 SYSTICK 實現精準延時 1.4 小技巧:SYSTICK 的低功耗優化 2. SYSTICK 中斷:讓你的程序“活”起來 2.1 配置 SYSTICK 中斷 2.2 實戰:用 S…

Sa-Token:輕量級Java權限認證框架使用指南

一、Sa-Token簡介 Sa-Token 是一個專注于權限認證的輕量級 Java 框架&#xff0c;旨在簡化登錄認證、權限控制等功能的實現。其核心功能包括&#xff1a; 登錄認證&#xff1a;通過 Token 機制管理用戶會話&#xff0c;支持單點登錄&#xff08;SSO&#xff09;。權限認證&am…