redis读写锁需通过redissonclient动态获取,不可@autowired注入;必须按业务标识设key、配对加解锁、用带超时的trylock、finally判空释放,且注意watchdog续期与key生命周期管理。

Redis读写锁不是直接用 RReadWriteLock 就能生效的
Spring Boot 里 RReadWriteLock 是 Redisson 提供的分布式读写锁接口,但它**不会自动绑定业务逻辑或事务边界**。你 new 一个、lock()、unlock(),看起来像 Java 的 ReentrantReadWriteLock,但实际行为完全取决于你怎么调度、超时怎么设、异常是否兜底——稍不注意就锁不住、死锁、或锁被提前释放。
必须用 RedissonClient 获取 RReadWriteLock,不能靠 @Autowired 注入实例
RReadWriteLock 是运行时按 key 动态生成的,不是 Spring 管理的单例 Bean。常见错误是写成:
@Autowired private RReadWriteLock readWriteLock; // ❌ 这会报 NullPointerException 或空指针
正确做法是每次需要时,从 RedissonClient 拿:
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
RReadWriteLock lock = redissonClient.getReadWriteLock("order:12345");
- key 必须带业务标识(比如订单 ID),否则多个资源共用一把锁,引发误阻塞
- 同一个 key 下的
readLock()和writeLock()才真正互斥;不同 key 之间完全无关 - 不要复用
RReadWriteLock实例:它内部缓存了连接状态,跨线程/异步场景下可能出错
读锁和写锁的获取必须严格配对,且要处理中断与超时
Redisson 的读写锁默认不响应线程中断,也不自动续期——如果你在写锁里做耗时操作(如调用外部 HTTP 接口),又没设好 tryLock(long, TimeUnit),很容易卡住整个服务。
- 务必使用带超时的
tryLock(3, TimeUnit.SECONDS),而不是lock() - 读锁可重入,但多个读锁之间不阻塞;写锁独占,且会阻塞所有读锁请求
- 解锁必须放在
finally块里,且要判空:if (lock != null) lock.unlock(); - 如果业务涉及异步(如
@Async),不能把锁对象传到另一个线程——Redisson 不支持跨线程 unlock
锁的可靠性依赖 Redis 部署模式和 leaseTime 设置
单节点 Redis 下,RReadWriteLock 能工作,但主从切换时可能丢失锁状态;集群模式下,Redisson 默认用 hash tag 保证锁 key 落在同一 slot,但若 key 设计不当(如带随机后缀),会导致锁分散、失效。
- 生产环境必须开启
watchdog(默认开启),否则锁会在leaseTime后自动释放,哪怕业务还没做完 - 不要把
leaseTime设为 -1(永不过期):Redisson 会禁用 watchdog,一旦客户端崩溃,锁永远无法释放 - watchdog 续期间隔默认 30s,可通过
Config.lockWatchdogTimeout调整,但不宜短于网络 RTT 的 2 倍
最常被忽略的是:锁 key 的生命周期和业务实体生命周期必须对齐。比如用 "cache:user:" + userId 加锁,但用户数据删了,锁还在——没人清,也没人等,只是白白占着资源。










