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