动态

详情 返回 返回

Redis分佈式鎖詳解 - 动态 详情

分佈式鎖的基本概念

分佈式鎖可以理解為"多個人搶同一個東西時,用一把鎖來保證只有一個人能拿到",但這裏的"多個人"不是單台機器上的多個線程,而是多台服務器(分佈式系統)。

例子:電商平台下單,庫存只有1件,同時有10個人在不同地方搶,這時候就需要一把"分佈式鎖",保證只有一個人能成功扣減庫存,避免超賣。

Redis分佈式鎖的實現方式

1. 最基礎的:用 setnx 命令("set if not exists")

原理:往Redis裏存一個key(比如 lock:stock),如果這個key不存在,就存成功(拿到鎖);如果已經存在,就存失敗(沒拿到鎖)。

使用方式

  • 搶鎖:執行 setnx lock:stock 1,成功就是拿到鎖,然後做操作(比如扣庫存)
  • 釋放鎖:操作完了,用 del lock:stock 刪除key,釋放鎖,讓別人能搶

類比:就像廁所隔間,門上的鎖(key)沒人用的時候,你才能鎖上(setnx成功),用完了開鎖(del)。

2. 加過期時間的:set 命令帶參數(推薦)

為什麼需要:如果拿到鎖的服務器突然宕機,沒來得及釋放鎖,這個key就會一直存在,別人永遠拿不到鎖(死鎖)。所以給鎖加個"過期時間",即使宕機,時間到了鎖會自動釋放。

使用方式:直接用 set lock:stock 1 EX 10 NXEX 10 是過期10秒,NX 是"不存在才設置",相當於 setnx +過期時間一步到位)

  • 搶鎖:執行上面的命令,成功就是拿到鎖,操作完手動 del 釋放
  • 自動釋放:如果服務器宕機,10秒後key自動消失,鎖釋放

3. 更完善的:加唯一標識+Lua腳本釋放

為什麼需要:假設A拿到鎖(過期時間10秒),但A的操作很慢,10秒還沒做完,鎖自動釋放了,這時候B拿到了鎖。這時候A操作完了,執行 del 會把B的鎖刪掉(誤刪)。

解決辦法

  • 存key的時候,value用"唯一標識"(比如UUID),代表"這把鎖是我的"
  • 釋放鎖時,先用腳本判斷"這個key的value是不是我的標識",是才刪除,不是就不刪

使用方式

  • 搶鎖set lock:stock uuid-xxx EX 10 NX(value是唯一標識)
  • 釋放鎖:用Lua腳本執行 if redis.call('get', 'lock:stock') == 'uuid-xxx' then return redis.call('del', 'lock:stock') else return 0 end

Redis分佈式鎖可能出現的問題及解決方案

1. 死鎖

問題:拿到鎖的節點宕機,沒釋放鎖,其他節點永遠拿不到鎖。

解決:給鎖加過期時間(set 命令帶 EX 參數),即使節點宕機,過期後鎖自動釋放。

2. 鎖過期但任務未完成

問題:鎖過期時間設短了,任務還在執行,鎖已釋放,其他節點趁機拿到鎖,導致"併發操作"。

解決

  • 預估任務耗時,設置足夠長的過期時間(留冗餘)
  • 用"鎖續期"機制(如開個後台線程,任務沒完成時,每隔一段時間延長鎖的過期時間,類似"看門狗")

3. 誤刪他人的鎖

問題:A的鎖過期後,B拿到鎖,A的任務恰好執行完,執行 del 命令誤刪了B的鎖。

解決

  • 加鎖時給 value 設唯一標識(如UUID),代表"這把鎖是我的"
  • 釋放鎖時用Lua腳本判斷:只有 value 匹配自己的標識時,才執行 del(避免誤刪)

4. Redis集羣"腦裂"問題

問題:Redis主從集羣中,主庫宕機,從庫還沒同步到"鎖已被持有"的信息,就升級為新主庫,導致新節點能再次加鎖,出現"雙鎖"。

解決

  • RedLock 算法(向多個獨立的Redis節點加鎖,超過半數節點加鎖成功才算拿到鎖,降低單節點同步問題的影響)
  • 業務層面容忍一定概率的衝突(中小業務可簡化,大業務再用複雜方案)

總結

實現方式對比

  • 最基礎setnx + del(但有死鎖風險)
  • 推薦基礎版set key value EX 時間 NX(加過期時間,防死鎖)
  • 更安全版:加唯一標識+Lua腳本釋放(防誤刪)

核心問題與解決

  • 死鎖:加過期時間
  • 鎖過期任務未完成:合理設置過期時間或鎖續期
  • 誤刪鎖:唯一標識+Lua腳本
  • 集羣腦裂:視業務複雜度選擇RedLock

使用場景

需要用鎖的場景:多節點競爭同一資源,必須保證操作的"原子性"。

user avatar actionopensource 头像 chang_lehung 头像 limaodebenma 头像 jiangyi 头像 motianlun_5d0766992e67a 头像 flydean 头像 xiongshihubao 头像 toplist 头像 coderdd 头像
点赞 9 用户, 点赞了这篇动态!
点赞

Add a new 评论

Some HTML is okay.