Redisson版本需严格匹配Spring Boot主版本:2.7.x用3.23.x,3.0+/3.1.x必须用3.24.0+;配置须按部署结构选singleServerConfig或clusterServersConfig;加锁必用tryLock并设合理leaseTime,unlock放finally中判空;事务或异步场景需注意锁上下文隔离。

Redisson 依赖怎么选版本才不踩 Spring Boot 版本坑
Redisson 和 Spring Boot 的版本兼容性不是“装上就能用”,而是容易在启动时抛 NoClassDefFoundError 或 BeanCreationException,尤其出现在 RedissonAutoConfiguration 类找不到、或 RedissonClient 注入失败时。
关键判断依据是 Spring Boot 主版本号:
- Spring Boot 2.7.x → 用
redisson-spring-boot-starter3.23.x(如3.23.4) - Spring Boot 3.0.x / 3.1.x → 必须用
redisson-spring-boot-starter3.24.0+,且底层依赖redisson≥ 3.24.0(否则会因 Jakarta EE 9 包路径报错) - 别直接引
redisson原生 jar,它不带自动配置;也别混用redisson-spring-data-32等非 starter 模块,容易引发RedisConnectionFactory冲突
示例(Maven):
<dependency> <groupId>org.redisson</groupId> <artifactId>redisson-spring-boot-starter</artifactId> <version>3.24.3</version> </dependency>
application.yml 里 Redisson 配置写不对,锁根本不会生效
很多人以为只要配了 Redis 地址就完事,结果 RLock 加锁成功但完全不阻塞、超时无效、甚至集群模式下锁跨节点失效——问题大概率出在 singleServerConfig / clusterServersConfig 顶层没对齐实际部署结构。
- 单机 Redis:必须用
singleServerConfig,且address格式为redis://127.0.0.1:6379(redis://前缀不能少,否则连不上) - Redis Cluster:必须用
clusterServersConfig,并确保nodeAddresses列出全部 master 节点(哪怕只写一个,Redisson 也会尝试自动发现,但首次发现失败会导致初始化卡住) -
lockWatchdogTimeout默认 30000ms(30 秒),如果业务方法可能执行超 30 秒,又没手动expire,看门狗续期失败会导致锁提前释放——建议显式设为业务最大耗时的 2 倍
常见错误配置:useLinuxNativeEpoll: true 在 Windows 下启动直接失败;threads 设成 0 会导致线程池拒绝所有异步任务,RLock.lock() 可能无限等待。
立即学习“Java免费学习笔记(深入)”;
加锁代码写法不对,分布式锁等于没锁
最典型的问题是把 RLock 当本地锁用:不检查返回值、不配超时、不保证 unlock 一定执行。结果出现死锁、锁残留、或看似加锁成功实则 key 没写入 Redis。
- 必须用
tryLock(waitTime, leaseTime, timeUnit),而不是无参lock()——后者在 Redis 不可用时会无限阻塞主线程 - leaseTime 必须小于 Redisson 的
lockWatchdogTimeout,否则看门狗无法续期(例如lockWatchdogTimeout=60000,leaseTime 就别设 120000) - unlock 必须放在
finally块里,且要判空:if (lock != null && lock.isHeldByCurrentThread()) { lock.unlock(); },否则锁被别人释放后你再 unlock 会抛IllegalMonitorStateException
简短安全写法:
RLock lock = redissonClient.getLock("order:create:" + userId);
if (lock.tryLock(3, 10, TimeUnit.SECONDS)) {
try {
// 执行业务
} finally {
if (lock.isHeldByCurrentThread()) lock.unlock();
}
}
Redisson 锁在事务或异步线程里失效的真相
Spring @Transactional 方法内加锁,或者用 @Async 异步执行加锁逻辑,经常出现“加锁成功但其他线程还能进来”——这不是 Redisson 的 bug,而是锁对象绑定的是当前线程上下文,而事务回滚或线程切换后,锁状态无法自动透传。
- @Transactional 中加锁,必须确保锁 key 足够唯一(比如带上订单 ID),且锁范围覆盖整个事务边界;不要指望“锁住方法就锁住数据库行”,二者隔离级别完全不同
- @Async 方法里加锁,
RLock实例不能从 Spring 容器直接注入(因为是 prototype 作用域),每次都要调用redissonClient.getLock(...)新建;否则多个异步线程共享同一个 lock 对象实例,导致isHeldByCurrentThread()判断失真 - 锁的 key 如果含变量(如
"user:" + id),务必确认 id 不为空或非法字符,否则 Redisson 会静默失败(日志里只报 WARN,不抛异常)
最容易被忽略的一点:Redisson 的锁默认使用 Lua 脚本实现,脚本里用了 KEYS[1] 和 ARGV[1],如果你的 Redis 集群开启了 lua-time-limit 限制,且脚本执行超时,会直接中断并返回错误,但 Java 层未必捕获到——建议在测试环境打开 Redisson 的 debug 日志级别,盯住 org.redisson.command.CommandAsyncService 输出。










