这是《Redis 零基础实战指南》的独立章节版。本章从概念、实操和生产排查三个视角展开,代码块保留了原书可直接运行的版本。 Redis 把底层数据结构做得很强,Redisson 则把分布式常用模式封装成 Java 风格 API。本章讲 Redisson 的基础接入、锁、限流、延迟队列与使用边界。
10.1 Redisson 是什么
Redisson 是基于 Redis 的 Java 驻留对象框架,提供:
- 分布式锁与读写锁;
- 原子数、限流器;
- 分布式 Map/Set/List;
- 延迟队列与优先队列;
- 布隆过滤器;
- 发布订阅、信号量、闭锁;
- Spring Cache 注解集成。
它解决的是“通用工程组件”,不是替代业务代码里的所有逻辑。
10.2 引入依赖
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-boot-starter</artifactId>
<version>3.27.2</version>
</dependency>
配置:
spring:
redis:
redisson:
config: |
singleServerConfig:
address: "redis://127.0.0.1:6379"
password: redis123
database: 0
connectionMinimumIdleSize: 10
connectionPoolSize: 50
connectTimeout: 1000
timeout: 1000
版本要与 Spring Boot、Redis Server、JDK 兼容矩阵匹配。
10.3 基础使用
@Autowired
private RedissonClient redisson;
public void demo() {
RBucket<String> bucket = redisson.getBucket("user:1001");
bucket.set("Tom", Duration.ofMinutes(10));
System.out.println(bucket.get());
RMap<String, Integer> cart = redisson.getMap("cart:user:1001");
cart.put("sku:2001", 2);
RScoredSortedSet<String> rank =
redisson.getScoredSortedSet("rank:game");
rank.add(100, "player:1");
}
这些对象本质仍是 Redis 数据结构,只是提供 Java API。
10.4 RedissonLock
RLock lock = redisson.getLock("lock:order:1001");
boolean locked = false;
try {
locked = lock.tryLock(100, 10, TimeUnit.SECONDS);
if (!locked) {
throw new BusyException("try lock failed");
}
doBusiness();
} finally {
if (locked && lock.isHeldByCurrentThread()) {
lock.unlock();
}
}
参数:
tryLock(waitTime, leaseTime, unit)
waitTime:最多等多久获取锁;leaseTime:锁持有时间;- 不传
leaseTime时启用看门狗自动续期。
10.5 看门狗机制
默认锁超时时间是 30 秒:
lockWatchdogTimeout=30000
当使用:
lock.lock();
lock.tryLock(1, TimeUnit.SECONDS);
没有显式 leaseTime 时,Redisson 会启动后台任务定期续期,通常每 10 秒重置到 30 秒。业务执行完成或客户端进程崩溃后,续期停止,锁最终自动过期。
看门狗解决“业务执行时间不可预估”的问题,但也带来风险:
- 业务死循环会一直持有锁;
- 客户端假死可能长时间阻塞其他节点;
- 因此关键业务仍要设置最大执行时间与熔断。
10.6 可重入锁
Redisson 的 RLock 是可重入锁:
RLock lock = redisson.getLock("lock:user:1001");
lock.lock();
try {
a(lock);
} finally {
lock.unlock();
}
void a(RLock lock) {
lock.lock();
try {
System.out.println("reentrant");
} finally {
lock.unlock();
}
}
底层使用 Hash 记录锁标识与重入次数,必须由持有线程 unlock。
10.7 公平锁与读写锁
公平锁:
RLock fairLock = redisson.getFairLock("lock:job");
等待线程按请求顺序获取锁,公平性带来额外开销,吞吐低于普通锁。
读写锁:
RReadWriteLock rwLock = redisson.getReadWriteLock("lock:config");
RLock readLock = rwLock.readLock();
RLock writeLock = rwLock.writeLock();
- 读锁共享,多个读者可同时进入;
- 写锁互斥,写与读互斥;
- 适合读多写少且读操作可接受最终一致的配置/缓存场景。
10.8 信号量与闭锁
RSemaphore semaphore = redisson.getSemaphore("sem:export");
semaphore.trySetPermits(5);
if (semaphore.tryAcquire()) {
try {
doExport();
} finally {
semaphore.release();
}
}
限制并发任务数。闭锁:
RCountDownLatch latch = redisson.getCountDownLatch("latch:batch");
latch.trySetCount(3);
latch.await();
latch.countDown();
适合等待多个节点/阶段完成,但要注意 await 超时与任务失败清理。
10.9 分布式限流
RRateLimiter limiter =
redisson.getRateLimiter("rate:login:user:1001");
limiter.trySetRate(RateType.OVERALL, 10, 1, RateIntervalUnit.SECONDS);
if (!limiter.tryAcquire()) {
throw new TooManyRequestException();
}
适用场景:
- 每用户登录/短信次数;
- 每接口 QPS;
- 每 API Key 调用限额。
精确滑动窗口可用 ZSet 自行实现,窗口大小按业务选择。全局强限流还要考虑 Redis 故障时的降级策略。
10.10 延迟队列
RBlockingQueue<String> queue =
redisson.getBlockingQueue("queue:order:timeout");
RDelayedQueue<String> delayedQueue =
redisson.getDelayedQueue(queue);
delayedQueue.offer("order:1001", 30, TimeUnit.MINUTES);
String orderId = queue.take(); // 到期后转移,再消费
delayedQueue.destroy();
适合订单超时关闭、重试延迟、提醒任务。生产还要处理:
- 消费失败重试;
- 幂等;
- 服务重启后的恢复;
- 队列监控与告警。
大规模任务调度可评估 RocketMQ 延迟消息、Kafka + 定时器、ElasticJob/XXL-JOB。
10.11 布隆过滤器
RBloomFilter<Long> filter =
redisson.getBloomFilter("bloom:valid:product");
filter.tryInit(1_000_000L, 0.01);
filter.add(10001L);
boolean mayContain = filter.contains(10002L);
特点:
- 可能误判存在,不会漏判存在;
- 标准布隆过滤器不支持删除;
- 需要预估容量和误判率,超过容量后误判上升。
适合缓存穿透防护、黑名单初筛、推荐去重初筛。
10.12 使用边界
Redisson 很方便,但不要把所有业务逻辑都搬进 Redis:
- 复杂状态流转仍应在数据库/服务层建模;
- 大量分布式对象操作可能形成大 key 和慢脚本;
- Redis 故障时锁、限流、延迟队列都会受影响;
- 与 Lettuce/Jedis 混用时要统一连接池和监控;
- 所有分布式组件都要有超时、降级和告警。
本章小结
- Redisson 提供锁、限流、延迟队列、信号量、布隆过滤器等分布式组件;
- RLock 支持可重入与看门狗续期,但必须正确 unlock;
- 无 leaseTime 才启用看门狗,显式 leaseTime 则到期自动释放;
- 延迟队列适合中小规模超时任务;
- Redisson 是效率工具,不改变 Redis 的容量、故障与一致性约束。
思考题
- 显式设置
leaseTime=5s后看门狗还会续期吗?为什么? - Redisson 锁释放失败有哪些常见原因?
- 布隆过滤器为什么能防穿透,但不能完全替代数据库存在性校验?