应用场景
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) then redis.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 算法需要多数节点确认
-
网络分区时可能有脑裂问题
-