一、為什么需要分布式鎖
在單機應用中,synchronized
或 ReentrantLock
足以解決并發問題。但在 分布式系統 中,多臺服務器之間共享同一個資源時,如果沒有鎖,很可能出現 超賣、重復扣減、數據不一致 等問題。
因此,分布式鎖應運而生,Redis 因其高性能與豐富指令,成為分布式鎖的常用實現工具。
二、Redis 實現分布式鎖的基本原理
Redis 分布式鎖主要基于 SET key value NX EX time
命令實現,核心思路:
加鎖:
使用
SETNX
保證 key 不存在時才能成功設置。使用
EX
設置過期時間,避免死鎖。value 通常設置為隨機值,用于標識鎖的持有者。
解鎖:
判斷當前鎖的 value 是否是自己設置的隨機值。
只有持有者才能釋放鎖。
使用 Lua 腳本保證“查詢 value + 刪除 key”的原子性。
這樣可以保證:
互斥性:同一時刻只有一個客戶端獲取鎖。
避免死鎖:即使客戶端異常宕機,鎖也會自動過期釋放。
可重入/安全解鎖:通過 value 標識持有者,防止誤刪別人的鎖。
三、可能存在的問題
鎖過期導致并發
如果業務邏輯執行時間 > 鎖過期時間,可能導致鎖自動釋放,其他客戶端拿到鎖,出現數據不一致。
主從復制延遲問題
在 Redis 主從架構下,如果主節點寫入成功但未同步到從節點,主節點宕機后從節點被提升為主,會導致鎖丟失。
不可重入性
同一個線程多次加鎖會失敗,需要額外機制實現可重入。
四、改進策略
1. 合理設置過期時間
根據業務邏輯耗時設置合理的鎖過期時間。
可結合 鎖續期機制:在后臺定時任務中為鎖自動續期(如 Redisson 的 WatchDog)。
2. 使用 Lua 腳本保證原子性
解鎖必須使用 Lua 腳本,保證“判斷 value + 刪除 key”操作的原子性。
3. Redlock 算法(Redis 官方提出)
通過 多個 Redis 實例 獲取鎖,必須在大多數節點上成功才算加鎖成功。
提高了分布式鎖的可靠性,避免因單點故障導致鎖失效。
4. 引入 Redisson 框架
Redisson 封裝了分布式鎖,支持可重入鎖、公平鎖、讀寫鎖、自動續期等功能。
在實際業務中更推薦使用,而不是自己手寫。
五、典型應用場景
電商秒殺:防止超賣。
庫存扣減:保證同一商品庫存不會被多次扣減。
訂單防重:防止重復提交訂單。