加鎖原理
# 如果鎖不存在
if (redis.call('exists', KEYS[1]) == 0) then# hash結構,鎖名稱為key,線程唯一標識為itemKey,itemValue為一個計數器。支持相同客戶端線程可重入,每次加鎖計數器+1.redis.call('hincrby', KEYS[1], ARGV[2], 1);# 設置過期時間redis.call('pexpire', KEYS[1], ARGV[1]);# 成功獲取鎖返回nullreturn nil;
end ;
#如果是當前線程占有分布式鎖,允許重入鎖
if (redis.call('hexists', KEYS[1], ARGV[2]) == 1) then# 將鎖重入計數器自增1.redis.call('hincrby', KEYS[1], ARGV[2], 1);# 設置過期時間redis.call('pexpire', KEYS[1], ARGV[1]);# 成功獲取鎖返回nullreturn nil;
end ;
#如果獲取不到鎖,返回鎖剩余過期時間,方便后續代碼設置等待超時時間
return redis.call('pttl', KEYS[1]);
在分布式鎖中,采用hash結構用來存儲鎖,其中大key表示表示這把鎖是否存在,用小key表示當前這把鎖被哪個線程持有。HINCRBY
可以在 KEYS[1]
(哈希鍵)不存在時直接創建并執行遞增操作。
KEYS[1] : 鎖名稱
ARGV[1]: 鎖失效時間
ARGV[2]: uuid + “:” + threadId; 鎖的小key,客戶端唯一標識

圖1處:判斷獲取鎖是否等待(waitTime)超時,如果等待超時則直接返回獲取鎖失敗。
圖2處:如果等待未超時,則嘗試訂閱解鎖channel。
圖3處:獲取ReissonLockEntry(獲取成功表示訂閱成功),超時時長設置為當前剩余的等待時間(waitTime)。 如果獲取ReissonLockEntry超時,終止并取消訂閱解鎖消息channel,獲取鎖失敗。
直到獲取鎖成功或者超時失敗。 解鎖消息廣播給所有鎖競爭的客戶端,收到解鎖消息后,客戶端會有一個線程去重新競爭鎖。當有解鎖消息到達時,不需要恢復所有掛起的線程一起去競爭分布式鎖,只需要喚醒一個線程去和集群中其它節點搶奪就可以了。這樣好處是顯而易見的,避免了大量的無效Redis請求,因為鎖在集群中同一時刻只會有一個線程能持有。
解鎖原理
# 判斷鎖是否為自己持有,不為自己持有則不允許解鎖。
if (redis.call('hexists', KEYS[1], ARGV[3]) == 0) thenreturn nil;
end ;
# 由于支持可重入,所以這里需要判斷是否完全解鎖,每解一次鎖重入計數器減1.
local counter = redis.call('hincrby', KEYS[1], ARGV[3], -1);
if (counter > 0) then# 如果鎖還沒有完全解除,則延長鎖租用時間redis.call('pexpire', KEYS[1], ARGV[2]);return 0;
else# 刪除鎖redis.call('del', KEYS[1]);# 廣播解鎖消息redis.call('publish', KEYS[2], ARGV[1]);return 1;
end ;
return nil;
watch dog原理
Redisson 的看門狗機制(WatchDog)是一種自動續期機制,旨在確保任務執行期間鎖不會因超時而被誤釋放。
- 原理:當客戶端獲取到鎖后,Redisson 會啟動一個后臺定時任務(即看門狗)。在鎖的持有期間,看門狗會以默認間隔(10秒)不斷地續期,延長鎖的過期時間,使鎖的默認過期時間始終保持為30秒。這樣,只要任務未完成且客戶端仍然活躍,鎖就不會過期。
- 默認行為:默認情況下,Redisson 會開啟看門狗機制,無需開發者手動配置。如果不想啟用看門狗機制,可以在調用
tryLock
時指定leaseTime
參數。 - leaseTime設置的影響:如果顯式設置
leaseTime
(例如通過tryLock(waitTime, leaseTime, TimeUnit.SECONDS)
),看門狗機制將不會啟動。鎖會在leaseTime
到期時自動釋放。當鎖超時時間為 -1 時,而且獲取鎖成功時,會啟動看門狗定時任務自動續鎖。
在 Redisson
中,tryLock(waitTime, leaseTime, TimeUnit.SECONDS)
方法是一個嘗試獲取分布式鎖的非阻塞方法,通過等待和設置鎖的租約時間來控制鎖的行為。
參數解釋
- waitTime:最大等待時間,即在嘗試獲取鎖時,線程等待的最大時間。如果在這段時間內鎖沒有被其他線程釋放,當前線程會放棄獲取鎖,返回
false
。 - leaseTime:鎖的租約時間,即鎖的自動釋放時間。如果成功獲取鎖后,線程在
leaseTime
時間內沒有手動釋放鎖,鎖將自動失效并釋放給其他線程。這個參數用于確保鎖不會一直持有,避免死鎖。 - TimeUnit:時間單位,可以設置為秒、毫秒等