一、分布式鎖的核心概念
分布式鎖是一種在分布式系統環境下,用于保證多個進程/節點對共享資源實現互斥訪問的機制。其本質是通過某種中間件(如Redis、ZooKeeper等)實現跨節點的鎖控制,確保在分布式環境中,同一時刻只有一個客戶端能獲取鎖并執行關鍵操作,避免出現并發沖突。
二、分布式鎖應用場景
場景1:分布式定時任務重復執行
- 業務背景:多個服務器節點部署相同的定時任務(如每日生成報表),需避免重復執行。
- 無分布式鎖的問題:
- 節點A和節點B在同一時間觸發任務;
- 兩個節點同時生成報表,導致數據重復寫入或資源浪費。
- 分布式鎖的作用:
任務執行前先獲取鎖,只有獲取鎖的節點能執行任務,其他節點等待或跳過,避免重復操作。
場景2:微服務接口冪等性保障
- 業務背景:支付接口可能因網絡重試導致多次調用,需保證同一筆支付只扣款一次。
- 無分布式鎖的問題:
- 用戶點擊支付后,因網絡延遲導致客戶端重試;
- 多個支付請求同時到達服務器,可能多次扣除余額。
- 分布式鎖的作用:
以訂單ID為鍵獲取分布式鎖,確保同一訂單的支付請求僅能被處理一次,實現冪等性。
三、分布式鎖核心特性與需求
分布式鎖需滿足以下關鍵特性:
- 互斥性:同一時刻僅一個節點持有鎖;
- 安全性:鎖只能由持有者釋放,避免誤釋放(如用唯一標識校驗);
- 容錯性:節點崩潰時鎖需自動失效(如超時機制);
- 可用性:中間件集群故障時,鎖服務仍能正常工作(如ZooKeeper的選舉機制)。
四、分布式鎖常見的實現方式
(一)基于關系型數據庫(如MySQL)的實現
1. 實現原理
- 唯一索引方案:通過插入唯一索引記錄標識鎖狀態,插入成功即獲取鎖
- 排他鎖方案:使用
SELECT ... FOR UPDATE
語句加行鎖
2. 核心問題
問題類型 | 具體表現 |
---|---|
性能瓶頸 | 數據庫IO操作耗時高,并發場景下頻繁加鎖導致吞吐量驟降(TPS通常<1000) |
鎖失效缺失 | 無自動過期機制,客戶端崩潰會導致鎖永久占用,需額外實現定時任務清理死鎖 |
可靠性不足 | 主從切換時可能出現鎖丟失(如MySQL半同步復制延遲) |
集群復雜 | 需處理數據庫連接池管理、事務一致性等問題,實現復雜度高 |
3. 適用場景
- 小規模系統(QPS<100)
- 對性能要求極低的測試環境
- 無高可用需求的簡單場景
(二)基于Redis的分布式鎖
1. 實現演進
- 基礎方案:使用
SET NX key value
加鎖,DEL key
釋放鎖(存在誤刪風險) - 安全方案:
SET key value NX PX 30000
(加鎖時設置唯一標識+過期時間) - Redlock算法(多實例方案):
- 依次向N個Redis實例申請鎖
- 超過半數實例成功則認為獲取鎖
- 釋放鎖時向所有實例發送釋放請求
2. 核心優缺點
- 優勢:
- 高性能:單實例TPS可達10萬+,適合高并發場景
- 輕量級:純內存操作,實現簡單
- 靈活擴展:支持主從/集群模式
- 風險點:
- 主從切換時可能丟鎖(異步復制導致)
- 需嚴格控制過期時間(過短易誤釋放,過長導致死鎖)
3. Redlock算法實戰參數
參數 | 推薦值 | 說明 |
---|---|---|
實例數N | 5 | 保證半數以上節點可用(3節點需2成功,5節點需3成功) |
鎖過期時間 | 5-10s | 需大于網絡RTT+業務處理時間,建議為業務耗時的1.5倍 |
重試間隔 | 50-100ms | 失敗后隨機延遲重試,避免驚群效應 |
(三)基于ZooKeeper的分布式鎖
1. 實現原理
- 利用ZooKeeper的臨時順序節點特性:
- 客戶端在
/locks
路徑下創建臨時順序節點 - 檢查是否為最小序號節點,是則獲取鎖
- 非最小節點監聽前一節點刪除事件
- 釋放鎖時刪除臨時節點,觸發后續節點獲取鎖
- 客戶端在
2. 核心優勢
- 自動失效機制:客戶端崩潰時臨時節點自動刪除,避免死鎖
- 強一致性:基于ZAB協議保證分布式事務一致性
- 高可靠性:節點故障時通過選舉機制快速恢復
- 可重入性:可通過節點路徑記錄客戶端標識實現重入邏輯
3. 性能表現
- 單次鎖操作耗時約10-50ms(含網絡往返)
- 集群模式下吞吐量可達5000-10000TPS
- 適合對可靠性要求高于性能的場景