應用場景
RLock rLock = redissonClient.getLock(Constant_LOCK + request.getId());
try {boolean isLocked = rLock.tryLock();if (!isLocked) {throw new ServiceException(ErrConstant.OPERATION_FAILED, "請勿重復提交");}
源碼
public interface RLock extends Lock, RLockAsync {String getName();void lockInterruptibly(long var1, TimeUnit var3) throws InterruptedException;boolean tryLock(long var1, long var3, TimeUnit var5) throws InterruptedException;void lock(long var1, TimeUnit var3);boolean forceUnlock();boolean isLocked();boolean isHeldByThread(long var1);boolean isHeldByCurrentThread();int getHoldCount();long remainTimeToLive();
}
實際上?
tryLock 是lock接口方法,redisson重寫了
Redisson?tryLock(long time, TimeUnit unit)
?方法深度解析
Redisson 的?tryLock(long time, TimeUnit unit)
?方法是分布式鎖的核心 API 之一,下面我將從多個維度詳細解析其工作原理和使用場景。
方法簽名
java
boolean tryLock(long waitTime, long leaseTime, TimeUnit unit) throws InterruptedException;
核心特性解析
1. 參數含義
waitTime:獲取鎖的最大等待時間
leaseTime:鎖的持有時間(自動釋放時間)
unit:時間單位
2. 返回值
true
:成功獲取鎖false
:在等待時間內未獲取到鎖
底層實現機制
1. Redis 數據結構
使用 Hash 結構存儲鎖信息:
text
key: "lock_name" field: "客戶端ID:線程ID" value: 重入次數
2. Lua 腳本原子操作
Redisson 通過 Lua 腳本保證原子性:
lua
-- 嘗試獲取鎖的Lua腳本 if (redis.call('exists', KEYS[1]) == 0) thenredis.call('hincrby', KEYS[1], ARGV[2], 1)redis.call('pexpire', KEYS[1], ARGV[1])return nil end -- 已存在鎖時的處理...
3. 看門狗機制(leaseTime = -1 時)
默認情況下啟動看門狗
每 10 秒(默認)檢查并續期鎖
保持鎖直到顯式釋放
典型使用場景
1. 基本用法
java
RLock lock = redisson.getLock("myLock"); boolean isLocked = lock.tryLock(10, 30, TimeUnit.SECONDS); try {if (isLocked) {// 業務邏輯} } finally {if (isLocked) {lock.unlock();} }
2. 不同參數組合效果
waitTime | leaseTime | 行為特點 |
---|---|---|
0 | >0 | 立即嘗試,獲取失敗直接返回 |
>0 | >0 | 在指定時間內循環嘗試 |
>0 | -1 | 獲取成功后啟動看門狗自動續期 |
0 | -1 | 立即嘗試+自動續期 |
異常處理要點
InterruptedException:
等待期間線程被中斷會拋出
需要正確處理中斷狀態
鎖續期失敗:
看門狗續期失敗會自動釋放鎖
業務代碼應實現冪等性
性能優化建議
合理設置等待時間:
避免設置過長的 waitTime
根據業務平均處理時間設置 leaseTime
避免鎖競爭:
java
// 使用隨機退避 while (!lock.tryLock(50, 100, TimeUnit.MILLISECONDS)) {Thread.sleep(random.nextInt(100)); }
監控建議:
監控鎖等待時間
設置鎖等待超時告警
與其他方法的對比
方法 | 特點 | 適用場景 |
---|---|---|
lock() | 阻塞直到獲取鎖 | 必須獲取鎖的場景 |
tryLock() | 嘗試獲取,可設置超時 | 有限等待的場景 |
tryLock(0, ...) | 立即嘗試一次 | 非阻塞快速失敗場景 |
實現原理示意圖
text
[客戶端A] --(tryLock)--> [Redis服務器]|___ 1. 檢查鎖是否存在|___ 2. 不存在則獲取鎖|___ 3. 存在則等待重試|___ 4. 獲取成功啟動看門狗(leaseTime=-1)
使用注意事項
必須釋放鎖:
java
try {if (lock.tryLock(...)) {// ...} } finally {lock.unlock(); }
避免死鎖:
確保 leaseTime > 業務執行時間
或使用默認的看門狗機制
集群模式特殊處理:
RedLock 算法需要多數節點確認
網絡分區時可能有腦裂問題