一、Redis 分布式鎖:追求極致的性能
Redis 分布式鎖基于內存操作,其核心思想是在內存中設置一個唯一的鍵值對來表示鎖的持有。
1. 基礎實現(SETNX + Lua)
最簡單的實現是使用 SETNX(SET if Not eXists)命令:
加鎖:設置一個鍵,值為隨機值,并設置過期時間(防止死鎖)
SET lock_resource_name my_random_value NX PX 30000
#解鎖:使用Lua腳本保證原子性(檢查值再刪除)
if redis.call(“get”, KEYS[1]) == ARGV[1] then
return redis.call(“del”, KEYS[1])
else
return 0
end
2. 生產環境推薦(Redisson框架)
在實際生產中,強烈推薦使用 Java 的 Redisson 庫,它解決了基礎實現的諸多痛點:
? 看門狗機制(Watchdog):異步續期線程,在業務執行期間自動為鎖續期,避免業務未完成而鎖自動過期的問題。
? 可重入鎖:支持同一線程多次加鎖。
? Lua腳本原子性:所有操作都使用Lua腳本,保證原子性。
// Redisson 示例
RLock lock = redissonClient.getLock(“myLock”);
try {
lock.lock();
// … 執行業務邏輯
} finally {
lock.unlock();
}
3. Redis鎖的優勢與劣勢
? 優勢:
-
性能極高:基于內存操作,吞吐量大,延遲低,適用于高并發場景(如秒殺)。
-
實現簡單:API 直觀易懂,部署方便。
-
功能豐富:通過 Redisson 支持多種鎖類型(可重入、公平、讀寫鎖)。
? 劣勢:
-
一致性依賴:在 Redis 主從異步復制架構下,如果主節點宕機且鎖信息未同步到從節點,可能導致鎖失效,出現多個客戶端同時持有鎖的情況(盡管 Redlock 算法試圖解決此問題,但仍有爭議)。
-
非強一致性:本質上是 AP 系統,優先保證可用性,在網絡分區時可能犧牲一致性。
二、ZooKeeper 分布式鎖:追求絕對的可靠
ZooKeeper 是一個分布式協調服務,其分布式鎖基于 臨時順序節點 和 Watch 機制,實現了強一致性。
1. 核心實現(臨時順序節點 + Watch)
? 加鎖:所有客戶端在同一個鎖目錄(如 /locks/mylock)下創建臨時順序節點。
? 排隊:客戶端獲取目錄下所有子節點,判斷自己創建的節點是否為序號最小的。
? 監聽:如果不是最小的,客戶端只需監聽(Watch)比自己序號小的前一個節點的刪除事件,而無需監聽所有節點。
? 解鎖:當前一個節點被刪除(即鎖被釋放)時,ZooKeeper 會精準通知下一個客戶端,使其獲得鎖。
2. 生產環境推薦(Curator框架)
Apache Curator 庫封裝了 ZooKeeper 的復雜邏輯,提供了開箱即用的分布式鎖。
// Curator 示例
InterProcessMutex lock = new InterProcessMutex(client, “/locks/mylock”);
try {
if (lock.acquire(10, TimeUnit.SECONDS)) {
// … 執行業務邏輯
}
} finally {
lock.release();
}
- ZooKeeper鎖的優勢與劣勢
? 優勢:
? 強一致性(CP):基于 ZAB 協議,數據在集群內強一致,鎖模型非常可靠,不會出現腦裂導致的雙重加鎖。
? 自動釋放:鎖與客戶端 Session 綁定,如果客戶端宕機,其創建的臨時節點會自動刪除,鎖也隨之釋放,有效避免了死鎖。
? 公平鎖:節點順序生成,天然實現了公平的先來后到機制。
? 無驚群效應:通過 Watch 機制精準通知下一個等待者,避免了同時爭搶。
? 劣勢:
? 性能較低:每次加解鎖都需要創建、刪除節點,涉及網絡通信和磁盤寫入(日志),性能遠低于 Redis。
? 運維復雜:需要額外維護一個 ZooKeeper 集群,增加了系統復雜度。
三、核心差異對比一覽表
特性維度 Redis 分布式鎖 ZooKeeper 分布式鎖
一致性模型 最終一致性 (AP) 強一致性 (CP)
性能 高 (內存操作) 低 (需持久化日志)
可靠性 依賴配置和算法 (如 Redlock) 高 (基于 ZAB 協議)
鎖釋放 依賴超時 (手動或看門狗) 自動釋放 (臨時節點)
鎖類型 非公平鎖 (可配置公平鎖) 公平鎖 (順序節點)
驚群效應 可能發生 可避免 (精準Watch)
運維成本 低 (通常已有Redis) 高 (需維護ZK集群)
四、選型建議:如何選擇?
選擇沒有絕對的對錯,只有適合與否。
選擇 Redis 鎖的場景:
? 高并發、高性能需求是首要目標(如秒殺、搶購、緩存擊穿)。
? 可以接受極小概率下的鎖失效(如業務邏輯有冪等性等補償措施)。
? 系統已經部署了 Redis,希望減少外部依賴。
選擇 ZooKeeper 鎖的場景:
? 絕對可靠比性能更重要(如金融交易、核心賬務、主備選舉)。
? 鎖持有時間較長的業務流程,不希望引入復雜的超時和續期機制。
? 系統已經依賴 ZooKeeper 做其他協調服務(如配置中心、服務發現)。
一言以蔽之:追求極致性能用 Redis,追求絕對可靠用 ZooKeeper。