Redisson 解决分布式锁的不可重入、不可重试和超时释放问题 1. 不可重入 → 可重入锁问题基于SETNX的锁同一线程无法多次获取同一把锁会导致死锁。Redisson 方案使用 RedisHash 结构存储锁Key 为锁名Field 为线程唯一标识Value 为重入次数。加锁时先判断锁是否存在不存在则创建存在则判断线程标识是否一致一致则重入次数 1解锁时重入次数 -1减到 0 时才真正删除锁整个过程通过Lua 脚本保证原子性-- 获取锁简化版 if (redis.call(exists, KEYS[1]) 0) then redis.call(hset, KEYS[1], ARGV[1], 1); redis.call(pexpire, KEYS[1], ARGV[2]); return nil; end; if (redis.call(hexists, KEYS[1], ARGV[2]) 1) then redis.call(hincrby, KEYS[1], ARGV[2], 1); redis.call(pexpire, KEYS[1], ARGV[1]); return nil; end; return redis.call(pttl, KEYS[1]);2. 不可重试 → 基于 Pub/Sub 的等待重试问题SETNX获取锁只尝试一次失败后直接返回无法等待锁释放。Redisson 方案tryLock(waitTime, leaseTime, TimeUnit)方法支持在指定等待时间内循环重试。实现机制首次尝试获取锁成功直接返回失败则订阅锁释放事件Redis Pub/Sub 机制阻塞等待锁释放通知收到通知后再次尝试获取在waitTime内循环此过程超时则返回false核心优势避免了高频轮询对 Redis 的压力通过事件驱动实现高效等待。// 等待最多 100 秒获取锁锁有效期 30 秒 boolean isLocked lock.tryLock(100, 30, TimeUnit.SECONDS);3. 超时释放 → WatchDog看门狗自动续期问题锁设置过期时间防止死锁但如果业务执行时间超过过期时间锁会被提前释放导致线程安全问题。Redisson 方案看门狗机制WatchDog场景行为leaseTime -1默认启用看门狗默认锁过期时间 30 秒每 10 秒leaseTime / 3自动续期leaseTime 0用户指定不启用看门狗严格按指定时间释放看门狗是一个后台定时任务只要锁未被显式释放且客户端存活就会持续续期确保锁在业务执行完之前不会过期总结对比问题原生 Redis 锁Redisson 解决方案不可重入SETNX无法重入Hash 结构 重入计数器不可重试只尝试一次Pub/Sub 订阅 循环等待重试超时释放固定过期时间WatchDog 自动续期默认 30s每 10s 续期此外Redisson 还通过MultiLock解决了主从一致性问题要求多个 Redis 节点全部加锁成功才算获取锁成功