很多人接触 Redisson,是因为"分布式锁"。网上一搜,三行代码就能加锁:
java
RLock lock = redissonClient.getLock("myLock");
lock.lock();
// 业务逻辑
lock.unlock();
看起来简单又可靠。但用了一段时间后才发现:Redisson 的能力远不止加锁。它更像是把 Java 并发包(JUC)里的那些工具------ReentrantLock、Semaphore、CountDownLatch、BlockingQueue------搬到了分布式环境,并用 Redis 作为底层支撑。
而这一切,都通过一个核心对象:RedissonClient。
一、所有功能,都从 RedissonClient 来
无论你要用锁、队列、还是分布式集合,第一步永远是创建 RedissonClient:
java
Config config = new Config();
config.useSingleServer().setAddress("redis://127.0.0.1:6379");
RedissonClient client = Redisson.create(config);
之后的所有操作,都是它的方法:
-
client.getLock("order_lock") → 分布式可重入锁
-
client.getSemaphore("concurrent_limit") → 信号量
-
client.getCountDownLatch("startup_ready") → 倒计时门闩
-
client.getMap("user_profile") → 分布式 Map
-
client.getTopic("notification") → 发布订阅
Redisson 不是对 Jedis 或 Lettuce 的简单封装,而是重新设计了一套面向对象的 Redis 操作接口。你操作的不是 key 和 value,而是一个个有行为的对象。
二、分布式锁只是起点,不是全部
Redisson 的 RLock 确实比手写 SETNX + Lua 更可靠,主要因为它解决了几个实际问题:
1. 自动续期(Watchdog)
默认情况下,加锁成功后,Redisson 会启动一个后台线程,每 10 秒检查一次:如果当前线程还在持有这把锁,就自动延长过期时间(默认 30 秒)。
这样即使业务执行时间超过初始 TTL,也不会提前释放锁。
注意:如果你显式指定了超时时间,比如 lock.lock(10, TimeUnit.SECONDS),就不会触发自动续期。
2. 可重入
同一个线程可以多次获取同一把锁,内部用 Redis Hash 记录线程 ID 和重入次数。释放时逐次递减,归零才真正删 key。行为和 ReentrantLock 完全一致。
3. 更多锁类型
- 公平锁:client.getFairLock(),按请求顺序排队;
- 读写锁:client.getReadWriteLock(),读共享、写独占;
- 联锁:new RedissonMultiLock(lock1, lock2),多个资源同时锁定。这些都不是靠拼几个 Redis 命令就能轻松实现的。
三、Redisson 的"JUC 搬家计划"
除了锁,Redisson 几乎把整个 java.util.concurrent 包都复刻到了 Redis 上:
|------------------|-------------------|---------------|
| JUC 类 | Redisson 对应 | 典型用途 |
| Semaphore | RSemaphore | 限制并发访问数(如限流) |
| CountDownLatch | RCountDownLatch | 等待多个服务就绪 |
| BlockingQueue | RBlockingQueue | 跨服务任务队列 |
| DelayedQueue | RDelayedQueue | 延迟任务(如订单超时取消) |
| AtomicLong | RAtomicLong | 分布式计数器 |
举个例子:用 RCountDownLatch 等三个微服务启动完成:
java
RCountDownLatch latch = client.getCountDownLatch("services-ready");
latch.trySetCount(3); // 初始化为3
// 每个服务启动完调用
latch.countDown();
// 主控服务等待
latch.await(); // 阻塞直到计数归零
整个过程天然跨 JVM,且状态持久化在 Redis 中。
四、RMap:不只是存数据,还能监听变化
RMap 是对 Redis Hash 的封装,但它支持更多高级特性:
java
RMap<String, Order> orderMap = client.getMap("orders");
orderMap.addListener((name, entry, action) -> {
if (action == EntryEvent.Action.UPDATE) {
System.out.println("订单更新: " + entry.getKey());
}
}
);
你可以监听某个 key 的增删改事件,像本地 Map 一样响应变化,但作用于整个集群。
其他亮点:
- 本地缓存:RMapCache 支持 LRU 本地缓存,减少 Redis 访问;
- 单条过期:每个 entry 可单独设 TTL;
- 批量操作:fastPut()、putAll() 减少网络往返。
五、使用时要注意什么?
1、记得关闭客户端
否则连接不会释放,可能耗尽连接池。
client.shutdown(); // 应用退出时调用
2、锁的粒度要合理
锁太粗(如"global_lock")会成为瓶颈,太细(如每条记录一个锁)可能增加 Redis 压力。建议按业务维度划分,比如"order:123:lock"。
3、Watchdog 不能解决主从切换问题
Redis 主从异步复制,极端情况下可能丢锁。对强一致性要求极高的场景,需评估是否适用。
4、序列化影响性能
默认用 Jackson,如果存大量数据,可换FstCodec或KryoCodec提升速度。
六、结语
Redisson 提供的能力,其实早就写在它的 API 里了。很多人只用了 getLock(),是因为一开始的需求就是加锁。但当你遇到限流、延迟任务、跨节点协同、数据变更通知等问题时,不妨先看看 Redisson 是否已经有现成的组件。
它不神奇,只是把常见的分布式协作模式,用 Redis 实现了一遍,并封装成你熟悉的接口。用不用,取决于你是否知道它在那里。