核心性質
獨占性:對于同一把鎖,同一時刻只能被一個加鎖方獨占
健壯性:不能產生死鎖。如果有一個因為宕機無法主動解鎖,鎖也應該被正常加載
對稱性:加成和解鎖的使用方必須為同一個身份,不允許被非方釋放
高可用:當提供分布式鎖服務的基礎組件中存在少量節點發生故障時,不應該影響到分布式鎖服務的穩定性
實現類型
對 cpu 空轉以及阻塞協程兩種行為的損耗做出權衡
主動輪詢型:該模型類似于單機鎖中的主動輪詢 + cas 樂觀鎖模型,取鎖方會持續對分布式鎖發出嘗試獲取動作,如果鎖已被占用則會不斷發起重試,直到取鎖成功為止
watch 回調型:在取鎖方發現鎖已被他人占用時,會創建 watcher 監視器訂閱鎖的釋放事件,隨后不再發起主動取鎖的嘗試;當鎖被釋放后,取鎖方能通過之前創建的 watcher 感知到這一變化,然后再重新發起取鎖的嘗試動作
分布式場景中”輪詢“,背后存在的行為可能是一次甚至多次網絡 IO 請求.但是,watch 機制在實現過程中需要建立長連接完成 watch 監聽動作,也會存在一定的資源損耗
主動輪詢型
針對同一把分布式鎖,用同一條數據標識(redis中的string同一個key對應的value)
假如在插入之前不存在數據,插入成功,則被認定為加鎖
把從存儲介質中刪除類比成解鎖動作
假如在插入之前存在,則持續輪訓,直到數據被刪除,并有自己插入成功
由于是并發場景,需要保證【 (1)檢查數據是否已被插入(2)數據不存在則插入數據 】這兩個步驟之間是原子化不可拆分的(在 redis 中是 set only if not exist —— SETNX 操作)
死鎖問題
使用 redis 時,通過過期時間 expire time自動刪除.
過期機制問題:鎖的持有者并不能精確預判到自己持鎖后處理業務邏輯的實際耗時,假如因為一些異常情況導致占有鎖的使用方在業務處理流程中的耗時超過了設置的過期時間閾值,就會導致鎖被提前釋放,其他取鎖方可能取鎖成功,最終引起數據不一致的并發問題.
解決方案:在鎖的持有方未完成業務邏輯的處理時,會持續對分布式鎖的過期閾值進行延期操作.
弱一致性問題
redis是ap形式,為保證服務的吞吐性,主從節點之間的數據同步是異步延遲進行。
問題 :倘若 使用方 A 在 redis master 節點加鎖成功,但是對應的 kv 記錄在同步到 slave 之前,master 節點就宕機了. 此時未同步到這項數據的 slave 節點升為 master,這樣分布式鎖被 A 持有的“憑證” 就這樣憑空消失了. 于是不知情的使用方 B C D 都可能加鎖成功,于是就出現了一把鎖被多方同時持有的問題,導致分布式鎖最基本的獨占性遭到破壞.
watch 回調型
差別在于
倘若在插入數據時,發現該條記錄已經存在,說明鎖已被他人持有,此時選擇監聽這條數據記錄的刪除事件,當對應事件發生時說明鎖被釋放了,此時才繼續嘗試取鎖