Redisson
Redisson 是 Redis 官方协议上的 Java 客户端。它不只是封装 Redis 命令,还提供了很多分布式对象和工具,例如分布式锁、信号量、限流器、阻塞队列、延迟队列等。
Redisson 能做什么
| 能力 | 说明 |
|---|---|
| RLock | 分布式可重入锁 |
| RReadWriteLock | 分布式读写锁 |
| RSemaphore | 分布式信号量 |
| RRateLimiter | 分布式限流器 |
| RBlockingQueue | 分布式阻塞队列 |
| RDelayedQueue | 分布式延迟队列 |
加锁流程
mermaid
flowchart TD
A[调用 lock] --> B[执行 Lua 脚本]
B --> C{锁是否存在?}
C -->|不存在| D[写入锁 key 和线程标识]
C -->|当前线程持有| E[重入次数加 1]
C -->|其他线程持有| F[订阅释放消息并等待]
D --> G[启动看门狗续期]
E --> G为什么使用 Lua 脚本
Redis 单条命令是原子的,但加锁通常需要判断、写入、设置过期时间等多个步骤。Redisson 使用 Lua 脚本把多个步骤放在 Redis 服务端一次执行,保证原子性。
看门狗机制
如果调用 lock() 时没有指定过期时间,Redisson 会启动看门狗自动续期。只要业务线程还活着,锁就会定期续期,避免业务没执行完锁却过期。
如果指定了明确的 leaseTime,看门狗不会自动续期,到期后锁会自动释放。
目录
使用建议
- 优先给锁设置合理的等待时间,避免线程无限等待。
- 临界区代码要尽量短,不要在锁内执行慢接口。
- 解锁必须放在
finally中。 - 释放锁前要确认当前线程持有锁。
- 对强一致要求极高的场景,要评估 Redis 锁是否足够。
常见风险和排查
| 风险 | 产生原因 | 排查和处理 |
|---|---|---|
| 锁等待时间过长 | 业务在锁内执行慢接口或大事务 | 缩短临界区,设置 tryLock 等待时间 |
| 锁提前释放 | 指定的 leaseTime 小于业务执行时间 | 使用看门狗,或合理设置过期时间 |
| 解锁报错 | 当前线程并不持有锁 | 解锁前判断 isHeldByCurrentThread() |
| Redis 故障导致锁不可用 | 锁状态依赖 Redis | 关键业务要设计降级、补偿或人工处理 |
| 把锁当事务用 | Redis 锁只能控制并发入口 | 数据一致性仍要靠数据库事务和唯一约束 |
Redisson 能减少手写 Redis 锁的错误,但不能消除分布式系统的一致性风险。锁只保护临界区并发,不负责业务补偿、事务提交和外部接口幂等。
代码 Demo:Redisson 限流器
java
@Service
public class SmsRateLimitService {
private final RedissonClient redissonClient;
public boolean tryAcquire(String phone) {
RRateLimiter limiter = redissonClient.getRateLimiter("sms:limit:" + phone);
limiter.trySetRate(RateType.OVERALL, 1, 60, RateIntervalUnit.SECONDS);
return limiter.tryAcquire();
}
}使用:
java
if (!smsRateLimitService.tryAcquire(phone)) {
throw new BizException("发送太频繁,请稍后再试");
}这个 Demo 表示同一个手机号 60 秒内只允许获取 1 个令牌,适合短信验证码这类防刷场景。
