深入理解分布式鎖——以Redis為例

一、分布式鎖簡介

1、什么是分布式鎖
分布式鎖是一種在分布式系統環境下,通過多個節點對共享資源進行訪問控制的一種同步機制。它的主要目的是防止多個節點同時操作同一份數據,從而避免數據的不一致性。

  • 線程鎖:
    也被稱為互斥鎖(Mutex),主要用于控制同一進程中的多個線程對共享資源的訪問。
  • 進程鎖:
    進程鎖是用于控制同一臺機器上的多個進程對共享資源的訪問。進程鎖可以是系統級的,如文件鎖,也可以是用戶級的,如信號量(Semaphore)。
  • 分布式鎖:
    分布式鎖是用于控制分布式系統中的多個節點對共享資源的訪問。由于分布式系統中的節點可能位于不同的機器甚至不同的地理位置,因此分布式鎖的實現比線程鎖和進程鎖要復雜得多。分布式鎖需要在網絡中的多個節點之間進行協調,以保證鎖的唯一性和一致性。
    2、分布式鎖的特性
    分布式鎖主要有以下幾個特性:
    互斥性:在任何時刻,只有一個節點可以持有鎖。
    不會發生死鎖:如果一個節點崩潰,鎖可以被其他節點獲取。
    公平性:如果多個節點同時申請鎖,系統應該保證每個節點都有獲取鎖的機會。
    可重入性:同一個節點可以多次獲取同一個鎖,而不會被阻塞。
    高可用:鎖服務應該是高可用的,不能因為鎖服務的故障而影響整個系統的運行。

二、分布式鎖的基本原理

分布式鎖的基本步驟分布式鎖的基本原理可以分為以下幾個步驟:
請求鎖:當一個實例需要訪問共享資源時,它會向分布式鎖系統發送一個請求,試圖獲取一個鎖。
鎖定資源:分布式鎖系統會檢查是否有其他實例已經持有這個鎖。如果沒有,那么這個實例就會獲得鎖,并且有權訪問共享資源。如果有,那么這個實例就必須等待,直到鎖被釋放。
訪問資源:一旦實例獲取了鎖,它就可以安全地訪問共享資源,而不用擔心其他實例會同時訪問這個資源。
釋放鎖:當實例完成對共享資源的訪問后,它需要通知分布式鎖系統釋放鎖。這樣,其他正在等待的實例就可以獲取鎖,訪問共享資源。
在這里插入圖片描述
2. 分布式鎖實現的關鍵點
在實現分布式鎖時,通常會有一個中心節點(或者稱為鎖服務),所有需要獲取鎖的節點都需要向這個中心節點申請。
當一個節點申請鎖時,中心節點會檢查當前是否有其他節點持有鎖,如果沒有,則將鎖分配給申請的節點;如果有,則拒絕申請。當持有鎖的節點完成操作后,會向中心節點歸還鎖,此時其他的節點可以再次申請鎖。
在這里插入圖片描述

三、基于Redis的分布式鎖

Redis的基本介紹Redis是一個開源的,內存中的數據結構存儲系統,它可以用作數據庫、緩存和消息代理。
Redis 提供了多種命令和能力來支持實現分布式鎖SETNX 命令:
SETNX(Set if Not Exists)命令用于在 key 不存在時設置值。這是實現分布式鎖的關鍵命令,因為它能確保在同一時間只有一個客戶端能夠獲得鎖。EXPIRE 命令:
EXPIRE 命令用于為 key 設置過期時間。這對于避免死鎖非常重要,因為即使某個客戶端崩潰,鎖也會在一定時間后自動釋放。
DEL 命令:DEL 命令用于刪除 key。在釋放鎖時,需要使用此命令刪除對應的 key。
Lua 腳本:Redis 支持使用 Lua 腳本來執行一系列原子操作。這對于實現安全的分布式鎖非常有用,因為它可以確保在釋放鎖時檢查鎖的持有者。
RedLock 算法:Redis 官方推薦了一種名為 RedLock 的分布式鎖算法。RedLock 是一種基于多個 Redis 實例的分布式鎖算法,旨在提供更高的安全性和容錯能力。
一般,在實現Redis分布式鎖時,不分開使用SETNX和EXPIRE命令,而是使用SETNX的拓展命令 SET NX EX

 示例:SET my_key my_value NX EX 10 # 設置鍵值對, 超時時間為10s。 如果my_key存在,則不進行任何操作
  1. Redis實現分布式鎖的基本實現請求鎖假設我們有一個 Redis 鍵 my_lock,用于表示鎖的狀態。當一個客戶端想要獲取鎖時,它會嘗試使用 SETNX 命令來設置這個鍵。
SET my_lock<unique_value> NX EX <lock_timeout>

如果命令返回 OK,則表示客戶端成功獲取了鎖。如果返回 nil,則表示鎖已被其他客戶端持有。<unique_value>: 一個唯一的值,比如 UUID,用于標識鎖的持有者。
NX: 只有當 my_lock 不存在時,才會設置該鍵。這確保了同一時間只有一個客戶端能獲得鎖。
EX <lock_timeout>: 設置鎖的過期時間,防止因客戶端崩潰而導致的死鎖。
鎖續期為了防止鎖過早地因為過期而被釋放,可以在鎖快到期時進行續期操作。這可以通過定期檢查鎖的剩余時間,并在必要時使用 EXPIRE 命令來更新過期時間來實現。

檢查鎖是否仍由當前客戶端持有

if redis.call("get", "my_lock") ==<unique_value>" then# 續期鎖redis.call("EXPIRE", "my_lock", <new_lock_timeout>)
end

注意:上述代碼是一個簡化的 Lua 腳本示例,實際應用中可能需要更復雜的邏輯來處理續期操作。
釋放鎖當客戶端完成需要加鎖保護的操作后,應該釋放鎖。為了確保只有鎖的持有者才能釋放鎖,可以使用 Lua 腳本來執行釋放操作。

if redis.call("get", "my_lock") ==<unique_value>" thenreturn redis.call("del", "my_lock")
elsereturn 0 -- 鎖未被當前客戶端持有,無法釋放
end

這個 Lua 腳本首先檢查鎖是否仍由當前客戶端持有,如果是,則刪除 my_lock 鍵以釋放鎖。
3. Redis分布式鎖的使用場景Redis分布式鎖可以用于所有需要在分布式環境中同步訪問共享資源的場景。例如,電商秒殺活動中,為了防止超賣,可以使用Redis分布式鎖來保證同一時刻只有一個請求可以操作庫存。又如,在分布式計算中,為了防止重復計算,可以使用Redis分布式鎖來保證同一時刻只有一個節點可以進行計算。
4. Redis分布式鎖的優點和缺點
優點:性能高:由于Redis是基于內存的,因此Redis分布式鎖的性能非常高。實現簡單:Redis提供的命令可以很容易地實現分布式鎖。
缺點:不可重入:Redis分布式鎖默認是不可重入的,如果需要可重入,需要額外的邏輯來實現。非阻塞:Redis分布式鎖是非阻塞的,如果獲取鎖失敗,需要自己進行重試。安全性:如果Redis服務器出現故障,可能會導致鎖無法正常工作。

四、其他分布式鎖的實現方式

  1. 基于數據庫的分布式鎖
    數據庫分布式鎖是通過在數據庫中創建一個鎖表,表中包含鎖的名稱和鎖的狀態等信息。
    當一個節點需要獲取鎖時,它會在這個表中插入一條記錄,如果插入成功,那么這個節點就獲取到了鎖。當節點使用完鎖后,會刪除這條記錄,從而釋放鎖。
    這種方式的優點是實現簡單,缺點是性能較低,且如果數據庫出現故障,可能會影響到鎖的功能。
  2. 基于Zookeeper的分布式鎖
    Zookeeper是一個開源的分布式協調服務,它提供了一種高效且可靠的分布式鎖實現方式。
    在Zookeeper中,可以創建一個臨時節點作為鎖,當一個節點需要獲取鎖時,它會嘗試創建這個臨時節點,如果創建成功,那么這個節點就獲取到了鎖。
    當節點使用完鎖后,會刪除這個臨時節點,從而釋放鎖。如果節點崩潰,Zookeeper會自動刪除這個臨時節點,從而避免了死鎖的問題。
  3. 基于Etcd的分布式鎖Etcd是一個開源的分布式鍵值存儲系統,它也提供了一種分布式鎖的實現方式。Etcd的分布式鎖是通過創建一個帶有TTL(Time To Live)的鍵值對來實現的,當一個節點需要獲取鎖時,它會嘗試創建這個鍵值對,如果創建成功,那么這個節點就獲取到了鎖。當節點使用完鎖后,會刪除這個鍵值對,從而釋放鎖。如果節點崩潰,Etcd會自動刪除這個鍵值對,從而避免了死鎖的問題。
  4. 各種實現方式的比較
    在這里插入圖片描述

五、分布式鎖的常見問題和解決方案

  1. 死鎖問題
    問題:當一個客戶端獲取了鎖,但由于某些原因(如程序崩潰、異常等)無法釋放鎖時,會導致其他客戶端永遠無法獲取鎖。
    解決方案:設置鎖的過期時間。當鎖的持有者未能在過期時間內執行完畢并釋放鎖時,鎖將自動過期,從而允許其他客戶端獲取鎖。
  2. 鎖續命問題
    問題:如果一個操作需要的時間可能超過鎖的過期時間,那么在操作執行過程中鎖過期會導致其他客戶端獲取到鎖,從而產生并發問題。
    解決方案:使用鎖續命機制。在鎖持有者執行操作期間,可以定期檢查鎖是否即將過期,并在適當的時候對鎖進行續命,即重新設置鎖的過期時間。
    在這里插入圖片描述
  3. 鎖釋放問題
    問題:為確保數據的一致性,只有鎖的持有者才能釋放鎖。但在實際應用中,可能會出現誤解鎖的情況。
    解決方案:在設置鎖時,為鎖關聯一個唯一的值(如UUID)。在釋放鎖時,先檢查鎖的值是否與當前客戶端的值匹配,如果匹配則釋放鎖,否則不做任何操作。注意,鎖持有人的判斷和鎖的釋放應該在一個原子操作內完成。
  4. 鎖的公平性問題
    問題:在高并發環境中,如果多個節點同時請求獲取鎖,可能會出現“饑餓”現象,即某些節點長時間無法獲取到鎖。
    解決方案:引入隊列,將請求鎖的節點按照順序排隊。例如,在Zookeeper中,可以使用順序節點來實現公平鎖。
  5. 鎖的可重入性問題
    問題:在某些場景中,一個節點可能需要多次獲取同一個鎖,如果鎖不支持重入,可能會導致死鎖。解決方案:為鎖添加一個擁有者的概念,只有鎖的擁有者才能再次獲取到鎖。例如,在Redis中,可以將鎖的值設置為節點的唯一標識,獲取鎖時檢查鎖的值是否為自己的標識。
  6. 鎖的安全性問題
    問題:如果分布式鎖的存儲系統(如Redis、Zookeeper等)出現故障,可能會導致鎖無法正常工作。
    解決方案:使用高可用的存儲系統,如使用Redis集群或Zookeeper集群。另外,可以使用心跳機制來檢測存儲系統的狀態,如果檢測到故障,可以及時進行切換。

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

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

相關文章

yolo訓練用的數據集的數據結構

Football Players Detection using YOLOV11 可以在roboflow上標注 Sign in to Roboflow 訓練數據集只看這個data.yaml 里面是train的image地址和classnames 每個image一一對應一個label 第一個位是分類&#xff0c;0是classnames[0]對應的物體&#xff0c;現在是cuboid &…

Redis 使用及命令操作

文章目錄 一、基本命令二、redis 設置鍵的生存時間或過期時間三、SortSet 排序集合類型操作四、查看中文五、密碼設置和查看密碼的方法六、關于 Redis 的 database 相關基礎七、查看內存占用 一、基本命令 # 查看版本 redis-cli --version 結果&#xff1a;redis-cli 8.0.0red…

Java大師成長計劃之第13天:Java中的響應式編程

&#x1f4e2; 友情提示&#xff1a; 本文由銀河易創AI&#xff08;https://ai.eaigx.com&#xff09;平臺gpt-4o-mini模型輔助創作完成&#xff0c;旨在提供靈感參考與技術分享&#xff0c;文中關鍵數據、代碼與結論建議通過官方渠道驗證。 隨著現代應用程序的復雜性增加&…

華為私有協議Hybrid

實驗top圖 理論環節 1. 基本概念 Hybrid接口&#xff1a; 支持同時處理多個VLAN流量&#xff0c;且能針對不同VLAN配置是否攜帶標簽&#xff08;Tagged/Untagged&#xff09;。 核心特性&#xff1a; 靈活控制數據幀的標簽處理方式&#xff0c;適用于復雜網絡場景。 2. 工作…

K8s 常用命令、對象名稱縮寫匯總

K8s 常用命令、對象名稱縮寫匯總 前言 在之前的文章中已經陸續介紹過 Kubernetes 的部分命令&#xff0c;本文將專題介紹 Kubernetes 的常用命令&#xff0c;處理日常工作基本夠用了。 集群相關 1、查看集群信息 kubectl cluster-info # 輸出信息Kubernetes master is run…

【HDLBits刷題】Verilog Language——1.Basics

目錄 一、題目與題解 1.Simple wire&#xff08;簡單導線&#xff09; 2.Four wires&#xff08;4線&#xff09; 3.Inverter&#xff08;逆變器&#xff08;非門&#xff09;&#xff09; 4.AND gate &#xff08;與門&#xff09; 5. NOR gate &#xff08;或非門&am…

C語言|遞歸求n!

C語言| 函數的遞歸調用 【遞歸求n!】 0!1; 1!1 n! n*(n-1)*(n-2)*(n-3)*...*3*2*1; 【分析過程】 定義一個求n&#xff01;的函數&#xff0c;主函數直接調用 [ Factorial()函數 ] 1 用if語句去實現&#xff0c;把求n!的情況列舉出來 2 if條件有3個&#xff0c;n<0; n0||n…

Android第四次面試總結之Java基礎篇(補充)

一、設計原則高頻面試題&#xff08;附大廠真題解析&#xff09; 1. 單一職責原則&#xff08;SRP&#xff09;在 Android 開發中的應用&#xff08;字節跳動真題&#xff09; 真題&#xff1a;“你在項目中如何體現單一職責原則&#xff1f;舉例說明。”考點&#xff1a;結合…

OpenHarmony GPIO應用開發-LED

學習于&#xff1a; https://docs.openharmony.cn/pages/v5.0/zh-cn/device-dev/driver/driver-platform-gpio-develop.md https://docs.openharmony.cn/pages/v5.0/zh-cn/device-dev/driver/driver-platform-gpio-des.md 通過OpenHarmony官方文檔指導可獲知&#xff1a;芯片廠…

XILINX原語之——xpm_fifo_async(異步FIFO靈活設置位寬、深度)

目錄 一、"fwft"模式&#xff08;First-Word-Fall-Through read mode&#xff09; 1、寫FIFO 2、讀FIFO 二、"std"模式&#xff08;standard read mode&#xff09; 1、寫FIFO 2、讀FIFO 調用方式和xpm_fifo_sync基本一致&#xff1a; XILINX原語之…

系統學習算法:動態規劃(斐波那契+路徑問題)

題目一&#xff1a; 思路&#xff1a; 作為動態規劃的第一道題&#xff0c;這個題很有代表性且很簡單&#xff0c;適合入門 先理解題意&#xff0c;很簡單&#xff0c;就是斐波那契數列的加強版&#xff0c;從前兩個數變為前三個數 算法原理&#xff1a; 這五步可以說是所有…

《讓內容“活”起來:Flutter社交應用瀑布流布局的破界實踐》

用戶動態的展示方式如同舞臺的布景&#xff0c;直接影響著觀眾——用戶的體驗。而瀑布流布局&#xff0c;以其獨特的美感和高效的信息展示能力&#xff0c;成為眾多社交應用的心頭好。當我們滑動著Instagram、Pinterest&#xff0c;或是國內熱門的小紅書&#xff0c;那種內容如…

微機控制技術復習【一】

填空題&#xff1a; 簡答題&#xff1a; 1、什么是計算機控制系統?其典型形式有哪些? 2、給出 DDC &#xff08;直接數字控制&#xff09;控制系統結構框圖&#xff0c;并說明各組成部分的作用&#xff1f; 3、采樣周期選擇的理論依據是什么?工程應用中應如何選擇?選擇采樣…

前端學習基礎—VScode環境配置及html基礎知識

作為初學者&#xff0c;一個好的開發環境能極大地提高理解與學習的效率&#xff0c;本文分享我的VScode環境配置方法&#xff0c;涵蓋插件、主題、快捷鍵等&#xff0c;希望能助你快速搭建舒適邊界的前端學習環境。 一、VSCode環境配置 首先找到vscode插件商店&#xff0c;在這…

【一】 基本概念與應用領域【830數字圖像處理】

考綱 文章目錄 1 概念2005甄題【名詞解釋】2008、2012甄題【名詞解釋】可考題【簡答題】可考題【簡答題】 2 應用領域【了解】2.1 伽馬射線成像【核醫學影像】☆2.2 X射線成像2.3 紫外波段成像2.4 可見光和紅外波段成像2.5 微波波段成像2.6 無線電波段成像2.7 電子顯微鏡成像2…

QuecPython錯誤碼匯總

QuecPython中定義的各種錯誤代碼常量 錯誤碼常量錯誤碼釋義QUEC_PY_FAIL-1Generic failure codesQUEC_PY_OK0Quec_py value indicating success (no error)QUEC_PY_EPERM1Operation not permittedQUEC_PY_ENOENT2No such file or directoryQUEC_PY_ESRCH3No such processQUEC_…

C++學習-入門到精通-【4】函數與遞歸入門

C學習-入門到精通-【4】函數與遞歸入門 函數與遞歸入門 C學習-入門到精通-【4】函數與遞歸入門一、 數學庫函數sqrt()ceil()cos()exp()fabs()floor()fmod()log()log10()pow()sin()tan()總結 二、具有多個形參的函數定義三、函數原型、函數簽名和實參的強制類型轉換函數原型函數…

天線測試報告解讀學習

提示&#xff1a;文章寫完后&#xff0c;目錄可以自動生成&#xff0c;如何生成可參考右邊的幫助文檔 文章目錄 前言一、無源測試和有源測試二、無源測試報告1.駐波2.回損3.史密斯圓圖4.效率5.增益6.天線方向圖7.天線隔離度8.無源測試總結 三、有源測試報告1.TRP與TIS2.測試指標…

GEC6818蜂鳴器驅動開發

相關知識&#xff1a;Linux設備驅動開發 insmod 編譯好的.ko文件后再運行beep_app.c編譯完成的可執行文件即可使板子蜂鳴。 beep_drv.c: #include <linux/module.h> //包含了加載模塊時需要使用的大量符號和函數聲明 #include <linux/kernel.h> //包含了printk內…

電腦定時管家!Wise Auto Shutdown 深度測評:多任務執行 + 靈活定時

各位電腦小達人&#xff0c;今天給大家介紹一款超厲害的Windows系統定時任務管理工具——Wise Auto Shutdown&#xff01;這玩意兒就像電腦的貼心小管家&#xff0c;能自動執行關機、重啟這些操作&#xff0c;時間設定靈活得很&#xff0c;還有提醒機制呢。下面我給大家好好嘮嘮…