Redisson 作为基于 Redis 的 Java 分布式框架,提供了丰富的分布式数据结构和服务,让开发者可以像操作本地 Java 对象一样处理分布式环境下的数据。下面详细讲解其核心组件:分布式锁 、 分布式集合 、 分布式对象 。
一、Redisson 分布式锁
分布式锁是 Redisson 最核心的功能之一,用于解决分布式系统中多节点并发竞争共享资源的问题。它基于 Redis 实现,同时弥补了原生 Redis 锁的缺陷(如不可重入、无自动续期等)。
1. 核心特性
- 可重入性 :同一线程可多次获取同一把锁,避免死锁(类似 Java 的
ReentrantLock)。
- 自动续期(WatchDog 机制) :若持有锁的线程未完成业务,会自动延长锁的过期时间(默认 30 秒续期一次),防止锁提前释放。
- 非阻塞获取 :支持tryLock()方法,可指定等待时间,避免无限阻塞。
- 公平锁 / 非公平锁 :公平锁按请求顺序分配锁,避免线程饥饿;非公平锁随机分配,性能更高。
- 红锁(RedLock)**:针对 Redis 集群,通过在多个独立节点获取锁,提升锁的可靠性(避免单节点故障导致锁失效)。
2. 常见锁类型及用法
Redisson 提供了多种锁实现,适配不同场景:
| 锁类型 | 特点 | 适用场景 |
|---|---|---|
RLock | 可重入锁(默认) | 大多数分布式并发场景(如投标、库存扣减) |
RReadWriteLock | 读写锁(读共享、写互斥) | 读多写少场景(如商品详情查询与更新) |
RFairLock | 公平锁(按请求顺序获取) | 对顺序性要求高的场景(如任务队列执行) |
RedissonRedLock | 红锁(多节点锁) | Redis 集群环境,需极高可靠性(如支付操作) |
示例:可重入锁(RLock)
java
运行
@Service
public class BiddingService {
@Autowired
private RedissonClient redissonClient;
public void submitBid(Long projectId, Long userId) {
// 锁的key:同一用户对同一项目的投标互斥
String lockKey = "bid:lock:" + projectId + ":" + userId;
RLock lock = redissonClient.getLock(lockKey);
try {
// 尝试获取锁:最多等5秒,获取后30秒自动过期(实际会被WatchDog续期)
boolean locked = lock.tryLock(5, 30, TimeUnit.SECONDS);
if (locked) {
// 1. 验证资格(子步骤,可重入获取同一把锁)
validateQualification(projectId, userId);
// 2. 扣保证金
deductDeposit(userId, projectId);
// 3. 记录投标
recordBid(projectId, userId);
} else {
throw new RuntimeException("获取锁失败,请重试");
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
// 释放锁(仅当前线程持有锁时才释放)
if (lock.isHeldByCurrentThread()) {
lock.unlock();
}
}
}
// 子步骤:验证资格(可重入获取同一把锁)
private void validateQualification(Long projectId, Long userId) {
String lockKey = "bid:lock:" + projectId + ":" + userId;
RLock lock = redissonClient.getLock(lockKey);
try {
// 同一线程再次获取锁,直接成功(重入性)
lock.lock();
// 业务逻辑:检查用户是否符合投标资格
} finally {
if (lock.isHeldByCurrentThread()) {
lock.unlock(); // 重入次数-1
}
}
}
}
3. 实现原理
Redisson 分布式锁基于 Redis 的SET命令(带NX、PX参数)实现,核心逻辑:
- 获取锁时,向 Redis 写入键值对(
key=锁名称,value=UUID+线程ID),并设置过期时间。 - 可重入性通过 “计数器” 实现:同一线程再次获取锁时,Redis 中存储的计数器 + 1。
- WatchDog 机制:启动一个后台线程,每隔 10 秒(默认)检查锁是否仍被持有,若持有则延长过期时间。
二、Redisson 分布式集合
Redisson 提供了与 Java 集合 API 兼容的分布式集合,支持跨节点共享数据,同时保留集合的核心操作(如增删改查、交集、排序等)。
1. 核心特性
- 分布式共享 :集合数据存储在 Redis 中,所有节点可访问(解决本地集合无法跨节点共享的问题)。
- 操作原子性 :集合的增删改查操作通过 Redis 的原子命令实现,避免并发修改导致的数据不一致。
- 丰富功能 **:支持过期时间、监听器(数据变化时触发回调)、批量操作等高级特性。
2. 常见分布式集合及用法
Redisson 的分布式集合几乎覆盖了 Java Collections Framework 的所有类型,核心包括:
| 集合类型 | 对应 Redisson 类 | 特点 | 适用场景 |
|---|---|---|---|
| 映射(Map) | RMap | 支持键过期、值序列化、监听器 | 分布式缓存(如用户信息、商品数据) |
| 列表(List) | RList | 有序、可重复,支持索引操作 | 分布式队列、任务列表 |
| 集合(Set) | RSet | 无序、不可重复,支持交集 / 并集 | 标签管理、去重场景(如用户已读消息 ID) |
| 有序集(SortedSet) | RSortedSet | 按分数排序,支持范围查询 | 排行榜(如用户积分排名) |
| 队列(Queue) | RQueue | FIFO(先进先出) | 分布式任务队列 |
| 双端队列(Deque) | RDeque | 两端均可操作 | 双向任务调度 |
示例 1:RMap(分布式 Map)
java
运行
@Service
public class UserCacheService {
@Autowired
private RedissonClient redissonClient;
public void cacheUserInfo(Long userId, UserInfo userInfo) {
// 获取分布式Map(键为用户ID,值为用户信息)
RMap<Long, UserInfo> userMap = redissonClient.getMap("user:info");
// 存储数据(支持过期时间:1小时后自动删除)
userMap.put(userId, userInfo, 1, TimeUnit.HOURS);
// 读取数据
UserInfo cachedUser = userMap.get(userId);
// 监听数据变化(当键被修改时触发)
userMap.addListener((MapEntryListener<Long, UserInfo>) event -> {
if (event.getEventType() == EntryEventType.UPDATE) {
System.out.println("用户信息更新:" + event.getValue());
}
});
}
}
示例 2:RSortedSet(分布式有序集合,排行榜场景)
java
运行
@Service
public class RankingService {
@Autowired
private RedissonClient redissonClient;
// 新增用户积分
public void addUserScore(Long userId, int score) {
// 获取有序集合(按分数排序)
RSortedSet<Long> scoreSet = redissonClient.getSortedSet("user:ranking");
// 添加用户ID,分数作为排序依据
scoreSet.add(score, userId);
}
// 获取Top10用户
public List<Long> getTop10Users() {
RSortedSet<Long> scoreSet = redissonClient.getSortedSet("user:ranking");
// 按分数倒序取前10(从高到低)
return new ArrayList<>(scoreSet.valueRange(-10, -1));
}
}
三、Redisson 分布式对象
Redisson 提供了一系列分布式对象,用于在分布式环境中实现原子操作、对象共享等功能,弥补了 Java 原生对象无法跨节点共享的缺陷。
1. 核心特性
- 跨节点共享 :对象数据存储在 Redis 中,所有节点可访问(如分布式计数器、分布式 ID 生成器)。
- 原子操作 :基于 Redis 的原子命令实现,避免并发修改导致的数据不一致。
- 序列化支持 **:支持 Java 对象的序列化 / 反序列化,可直接存储复杂对象。
2. 常见分布式对象及用法
Redisson 的分布式对象覆盖了原子类、二进制对象、信号量等,核心包括:
| 对象类型 | 对应 Redisson 类 | 特点 | 适用场景 |
|---|---|---|---|
| 原子长整型 | RAtomicLong | 支持原子增减操作 | 分布式计数器(如接口调用次数、订单编号) |
| 二进制对象 | RBucket | 存储任意 Java 对象,支持过期 | 分布式缓存(如会话数据、临时结果) |
| 分布式 BitSet | RBitSet | 位操作(如置位、清零、与 / 或) | 权限控制(如用户角色掩码)、布隆过滤器 |
| 信号量(Semaphore) | RSemaphore | 控制并发访问数量 | 限流(如同时最多 100 个请求访问接口) |
| 可过期信号量 | RPermitExpirableSemaphore | 带过期时间的信号量 | 临时资源占用(如限时抢购资格) |
示例 1:RAtomicLong(分布式计数器)
java
运行
@Service
public class OrderCounterService {
@Autowired
private RedissonClient redissonClient;
// 生成唯一订单号(原子自增)
public Long generateOrderId() {
// 获取分布式原子长整型
RAtomicLong orderCounter = redissonClient.getAtomicLong("order:id:counter");
// 原子自增并返回新值(确保分布式环境下唯一)
return orderCounter.incrementAndGet();
}
}
示例 2:RBucket(分布式对象存储)
java
运行
@Service
public class SessionService {
@Autowired
private RedissonClient redissonClient;
// 存储用户会话(30分钟过期)
public void saveSession(String sessionId, UserSession session) {
// 获取二进制对象容器
RBucket<UserSession> sessionBucket = redissonClient.getBucket("session:" + sessionId);
// 存储对象,设置30分钟过期
sessionBucket.set(session, 30, TimeUnit.MINUTES);
}
// 获取用户会话
public UserSession getSession(String sessionId) {
RBucket<UserSession> sessionBucket = redissonClient.getBucket("session:" + sessionId);
return sessionBucket.get(); // 自动反序列化
}
}
示例 3:RSemaphore(分布式信号量,限流场景)
java
运行
@Service
public class LimitService {
@Autowired
private RedissonClient redissonClient;
// 初始化信号量:最多允许100个并发请求
@PostConstruct
public void initSemaphore() {
RSemaphore semaphore = redissonClient.getSemaphore("api:limit");
semaphore.trySetPermits(100); // 初始100个许可
}
// 接口访问前获取许可(限流)
public boolean tryAccess() {
RSemaphore semaphore = redissonClient.getSemaphore("api:limit");
// 尝试获取1个许可,最多等1秒
return semaphore.tryAcquire(1, 1, TimeUnit.SECONDS);
}
// 接口访问后释放许可
public void releaseAccess() {
RSemaphore semaphore = redissonClient.getSemaphore("api:limit");
semaphore.release(); // 释放1个许可
}
}
总结
Redisson 通过封装 Redis 的底层能力,提供了分布式锁、分布式集合、分布式对象三大核心组件,解决了分布式系统中的三大痛点:
-
分布式锁:解决多节点并发竞争资源的问题;
-
分布式集合:实现跨节点的数据共享与聚合操作;
-
分布式对象:提供原子操作与跨节点对象存储。
这些组件的 API 设计与 Java 原生 API 高度兼容,大幅降低了分布式开发的复杂度,让开发者可以专注于业务逻辑,而非分布式细节。