Redisson 是一个基于 Redis 的 Java 分布式协调服务框架,提供了丰富的分布式功能。本文介绍 Redisson 的常用技巧和最佳实践。
快速开始
Maven 依赖
xml
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-boot-starter</artifactId>
<version>3.24.3</version>
</dependency>
配置类
java
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class RedissonConfig {
@Bean
public RedissonClient redissonClient() {
Config config = new Config();
config.useSingleServer()
.setAddress("redis://localhost:6379")
.setDatabase(0)
.setPassword("redis123");
return Redisson.create(config);
}
}
分布式锁
分布式锁是 Redisson 最常用的功能之一。
可重入锁(Reentrant Lock)
java
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Service;
import java.util.concurrent.TimeUnit;
@Slf4j
@Service
@RequiredArgsConstructor
public class DistributedLockService {
private final RedissonClient redissonClient;
private static final String LOCK_KEY = "business:lock:";
// 简单加锁(默认 30 秒)
public boolean doWithLock(String businessId, Runnable task) {
RLock lock = redissonClient.getLock(LOCK_KEY + businessId);
try {
// 尝试加锁,最多等待 10 秒,持有锁 30 秒
boolean acquired = lock.tryLock(10, 30, TimeUnit.SECONDS);
if (!acquired) {
log.warn("获取锁失败: {}", businessId);
return false;
}
task.run();
return true;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
log.error("获取锁被中断: {}", businessId, e);
return false;
} finally {
if (lock.isHeldByCurrentThread()) {
lock.unlock();
}
}
}
// 手动控制锁(适用于长时间操作)
public void doWithManualLock(String businessId, Runnable task, long leaseTime, TimeUnit unit) {
RLock lock = redissonClient.getLock(LOCK_KEY + businessId);
try {
// 使用看门狗机制,自动续期
lock.lock(leaseTime, unit);
task.run();
} finally {
lock.unlock();
}
}
}
公平锁(Fair Lock)
java
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
@Service
@RequiredArgsConstructor
public class FairLockService {
private final RedissonClient redissonClient;
private static final String FAIR_LOCK_KEY = "business:fair-lock:";
// 公平锁:按照请求顺序获取锁,防止饥饿
public boolean executeWithFairLock(String orderId, Runnable task) {
RLock lock = redissonClient.getFairLock(FAIR_LOCK_KEY + orderId);
try {
if (lock.tryLock(10, 60, TimeUnit.SECONDS)) {
task.run();
return true;
}
return false;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
} finally {
if (lock.isHeldByCurrentThread()) {
lock.unlock();
}
}
}
}
读写锁(ReadWrite Lock)
java
import org.redisson.api.RReadWriteLock;
import org.redisson.api.RedissonClient;
@Service
@RequiredArgsConstructor
public class ReadWriteLockService {
private final RedissonClient redissonClient;
private static final String RW_LOCK_KEY = "business:data:";
// 读操作:多个线程可以同时读取
public String readWithLock(String dataId, Supplier<String> readFunc) {
RReadWriteLock rwLock = redissonClient.getReadWriteLock(RW_LOCK_KEY + dataId);
RLock readLock = rwLock.readLock();
try {
readLock.lock(30, TimeUnit.SECONDS);
return readFunc.get();
} finally {
if (readLock.isHeldByCurrentThread()) {
readLock.unlock();
}
}
}
// 写操作:排他锁,写锁释放前其他线程无法读取或写入
public void writeWithLock(String dataId, Runnable writeFunc) {
RReadWriteLock rwLock = redissonClient.getReadWriteLock(RW_LOCK_KEY + dataId);
RLock writeLock = rwLock.writeLock();
try {
writeLock.lock(30, TimeUnit.SECONDS);
writeFunc.run();
} finally {
if (writeLock.isHeldByCurrentThread()) {
writeLock.unlock();
}
}
}
}
分布式锁的最佳实践
java
import org.redisson.api.RLock;
@Slf4j
@Service
@RequiredArgsConstructor
public class LockBestPractice {
private final RedissonClient redissonClient;
// 锁的粒度要细,避免锁范围过大
private static final String PRODUCT_LOCK = "product:stock:";
private static final String ORDER_LOCK = "order:create:";
// 场景:库存扣减
public boolean decreaseStock(Long productId, int quantity) {
RLock lock = redissonClient.getLock(PRODUCT_LOCK + productId);
try {
if (lock.tryLock(5, 30, TimeUnit.SECONDS)) {
// 执行库存扣减逻辑
return doDecreaseStock(productId, quantity);
}
return false;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
} finally {
lock.unlock();
}
}
private boolean doDecreaseStock(Long productId, int quantity) {
// 业务逻辑实现
return true;
}
// 使用看门狗机制,自动续期
public void executeWithWatchdog(String lockKey, Runnable task) {
RLock lock = redissonClient.getLock(lockKey);
// 不指定leaseTime,看门狗会每 30 秒自动续期
lock.lock();
try {
task.run();
} finally {
lock.unlock();
}
}
}
分布式集合
分布式 Map
java
import org.redisson.api.RMap;
import org.redisson.api.RedissonClient;
import java.util.concurrent.TimeUnit;
@Service
@RequiredArgsConstructor
public class DistributedMapService {
private final RedissonClient redissonClient;
private static final String CACHE_MAP = "app:cache:";
// 缓存用户信息
public void cacheUser(Long userId, User user) {
RMap<Long, User> map = redissonClient.getMap(CACHE_MAP + "user");
map.put(userId, user, 30, TimeUnit.MINUTES);
}
// 获取缓存
public User getCachedUser(Long userId) {
RMap<Long, User> map = redissonClient.getMap(CACHE_MAP + "user");
return map.get(userId);
}
// 分布式本地缓存(减少 Redis 网络开销)
public RMap<Long, User> getLocalCacheMap(String mapName) {
RMap<Long, User> map = redissonClient.getMap(mapName);
// 启用本地缓存
map.setLocalCachePolicy(LocalCachedMapOptions.defaultLocalCacheOptions());
return map;
}
// 原子操作
public Long incrementUserVisitCount(Long userId) {
RMap<String, Long> map = redissonClient.getMap(CACHE_MAP + "visit");
return map.addAndGet("user:" + userId, 1L);
}
}
分布式 Set
java
import org.redisson.api.RSet;
import org.redisson.api.RedissonClient;
import java.util.Set;
@Service
@RequiredArgsConstructor
public class DistributedSetService {
private final RedissonClient redissonClient;
private static final String ONLINE_USERS = "app:online:users";
private static final String HOT_PRODUCTS = "product:hot:";
// 用户上线
public void userOnline(Long userId) {
RSet<Long> onlineSet = redissonClient.getSet(ONLINE_USERS);
onlineSet.add(userId);
}
// 用户下线
public void userOffline(Long userId) {
RSet<Long> onlineSet = redissonClient.getSet(ONLINE_USERS);
onlineSet.remove(userId);
}
// 获取在线用户数
public int getOnlineUserCount() {
RSet<Long> onlineSet = redissonClient.getSet(ONLINE_USERS);
return onlineSet.size();
}
// 判断用户是否在线
public boolean isUserOnline(Long userId) {
RSet<Long> onlineSet = redissonClient.getSet(ONLINE_USERS);
return onlineSet.contains(userId);
}
// 批量操作
public void addHotProducts(Set<Long> productIds) {
RSet<Long> hotSet = redissonClient.getSet(HOT_PRODUCTS);
hotSet.addAll(productIds);
}
}
分布式 List
java
import org.redisson.api.RList;
import org.redisson.api.RedissonClient;
import java.util.List;
@Service
@RequiredArgsConstructor
public class DistributedListService {
private final RedissonClient redissonClient;
private static final String TASK_QUEUE = "app:tasks:";
private static final String PROCESSED_IDS = "app:processed:";
// 添加任务到队列
public void addTask(String queueName, Task task) {
RList<Task> list = redissonClient.getList(TASK_QUEUE + queueName);
list.add(task);
}
// 从队列获取任务
public Task pollTask(String queueName) {
RList<Task> list = redissonClient.getList(TASK_QUEUE + queueName);
if (list.isEmpty()) {
return null;
}
// 移除并返回最后一个元素
return list.removeLast();
}
// 使用阻塞队列更高效
public void useBlockingQueue(String queueName, Task task) {
RBlockingQueue<Task> queue = redissonClient.getBlockingQueue(queueName);
queue.offer(task);
}
// 获取已处理 ID 列表
public List<Long> getProcessedIds() {
RList<Long> list = redissonClient.getList(PROCESSED_IDS);
return list.readAll();
}
}
分布式对象
java
import org.redisson.api.RAtomicLong;
import org.redisson.api.RAtomicReference;
import org.redisson.api.RBloomFilter;
import org.redisson.api.RedissonClient;
@Service
@RequiredArgsConstructor
public class DistributedObjectService {
private final RedissonClient redissonClient;
// 分布式原子 Long
public void incrementSequence(String sequenceName) {
RAtomicLong sequence = redissonClient.getAtomicLong(sequenceName);
sequence.incrementAndGet();
}
public Long getCurrentSequence(String sequenceName) {
RAtomicLong sequence = redissonClient.getAtomicLong(sequenceName);
return sequence.get();
}
// 分布式原子引用
public void updateConfig(String configKey, ConfigData config) {
RAtomicReference<ConfigData> atomicRef = redissonClient.getAtomicReference(configKey);
atomicRef.set(config);
}
public ConfigData getConfig(String configKey) {
RAtomicReference<ConfigData> atomicRef = redissonClient.getAtomicReference(configKey);
return atomicRef.get();
}
// 布隆过滤器(用于去重、判断元素是否存在)
public void initBloomFilter(String filterName, int expectedInsertions, double falseProbability) {
RBloomFilter<Long> bloomFilter = redissonClient.getBloomFilter(filterName);
bloomFilter.tryInit(expectedInsertions, falseProbability);
}
public void addToBloomFilter(String filterName, Long value) {
RBloomFilter<Long> bloomFilter = redissonClient.getBloomFilter(filterName);
bloomFilter.add(value);
}
public boolean mightContain(String filterName, Long value) {
RBloomFilter<Long> bloomFilter = redissonClient.getBloomFilter(filterName);
return bloomFilter.mightContain(value);
}
}
分布式同步器
信号量(Semaphore)
java
import org.redisson.api.RSemaphore;
import org.redisson.api.RedissonClient;
import java.util.concurrent.TimeUnit;
@Service
@RequiredArgsConstructor
public class SemaphoreService {
private final RedissonClient redissonClient;
private static final String RESOURCE_SEMAPHORE = "resource:semaphore:";
// 初始化信号量(资源数量)
public void initSemaphore(String resourceId, int permits) {
RSemaphore semaphore = redissonClient.getSemaphore(RESOURCE_SEMAPHORE + resourceId);
semaphore.trySetPermits(permits);
}
// 获取许可证(阻塞)
public boolean acquire(String resourceId, long timeout, TimeUnit unit) throws InterruptedException {
RSemaphore semaphore = redissonClient.getSemaphore(RESOURCE_SEMAPHORE + resourceId);
return semaphore.tryAcquire(timeout, unit);
}
// 释放许可证
public void release(String resourceId) {
RSemaphore semaphore = redissonClient.getSemaphore(RESOURCE_SEMAPHORE + resourceId);
semaphore.release();
}
// 场景:限制并发数
public void doWithLimitedConcurrency(String resourceId, int maxConcurrency, Runnable task)
throws InterruptedException {
RSemaphore semaphore = redissonClient.getSemaphore(RESOURCE_SEMAPHORE + resourceId);
// 初始化信号量
semaphore.trySetPermits(maxConcurrency);
if (semaphore.tryAcquire(10, TimeUnit.SECONDS)) {
try {
task.run();
} finally {
semaphore.release();
}
}
}
}
倒计时门栓(CountDownLatch)
java
import org.redisson.api.RCountDownLatch;
import org.redisson.api.RedissonClient;
@Service
@RequiredArgsConstructor
public class CountDownLatchService {
private final RedissonClient redissonClient;
private static final String TASK_LATCH = "task:latch:";
// 主线程等待子任务完成
public void awaitSubTasks(String latchId, int taskCount, Runnable subTaskRunner)
throws InterruptedException {
RCountDownLatch latch = redissonClient.getCountDownLatch(TASK_LATCH + latchId);
latch.trySetCount(taskCount);
// 启动子任务
for (int i = 0; i < taskCount; i++) {
subTaskRunner.run();
}
// 等待所有子任务完成
latch.await();
}
// 子任务完成后调用
public void countDown(String latchId) {
RCountDownLatch latch = redissonClient.getCountDownLatch(TASK_LATCH + latchId);
latch.countDown();
}
// 场景:批量任务同步
public void executeBatchTasks(BatchTask batchTask) throws InterruptedException {
String latchId = "batch:" + batchTask.getBatchId();
RCountDownLatch latch = redissonClient.getCountDownLatch(TASK_LATCH + latchId);
latch.trySetCount(batchTask.getTaskCount());
// 提交任务到线程池
batchTask.submitTasks(task -> {
try {
task.execute();
} finally {
latch.countDown();
}
});
latch.await();
System.out.println("批量任务完成");
}
}
分布式消息
话题订阅(Pub/Sub)
java
import org.redisson.api.RTopic;
import org.redisson.api.RedissonClient;
import org.redisson.api.listener.MessageListener;
@Service
@RequiredArgsConstructor
public class PubSubService {
private final RedissonClient redissonClient;
private static final String TOPIC_NOTIFICATION = "app:notification:";
private static final String TOPIC_ORDER = "app:order:";
// 发布消息
public void publishNotification(Notification notification) {
RTopic<Notification> topic = redissonClient.getTopic(TOPIC_NOTIFICATION + notification.getType());
topic.publish(notification);
}
// 订阅消息
public void subscribeNotification(String notificationType, MessageListener<Notification> listener) {
RTopic<Notification> topic = redissonClient.getTopic(TOPIC_NOTIFICATION + notificationType);
topic.addListener(Notification.class, listener);
}
// 订单状态变更通知
public void publishOrderStatusChange(Order order) {
RTopic<Order> topic = redissonClient.getTopic(TOPIC_ORDER + "status");
topic.publish(order);
}
// 监听订单状态变更
public void listenOrderStatusChange(MessageListener<Order> listener) {
RTopic<Order> topic = redissonClient.getTopic(TOPIC_ORDER + "status");
topic.addListener(Order.class, listener);
}
}
分布式服务
分布式调度
java
import org.redisson.api.RScheduledExecutorService;
import org.redisson.api.RedissonClient;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
@Service
@RequiredArgsConstructor
public class ScheduledTaskService {
private final RedissonClient redissonClient;
private static final String SCHEDULED_EXECUTOR = "app:executor:";
// 延迟执行
public ScheduledFuture<?> delayExecute(Runnable task, long delay, TimeUnit unit) {
RScheduledExecutorService executor = redissonClient.getScheduledExecutor(SCHEDULED_EXECUTOR + "default");
return executor.schedule(task, delay, unit);
}
// 定时执行(cron 风格)
public ScheduledFuture<?> scheduleAtFixedRate(Runnable task, long initialDelay, long period, TimeUnit unit) {
RScheduledExecutorService executor = redissonClient.getScheduledExecutor(SCHEDULED_EXECUTOR + "rate");
return executor.scheduleAtFixedRate(task, initialDelay, period, unit);
}
// 定时执行(固定延迟)
public ScheduledFuture<?> scheduleWithFixedDelay(Runnable task, long initialDelay, long delay, TimeUnit unit) {
RScheduledExecutorService executor = redissonClient.getScheduledExecutor(SCHEDULED_EXECUTOR + "delay");
return executor.scheduleWithFixedDelay(task, initialDelay, delay, unit);
}
// 场景:定时清理过期数据
public void scheduleDataCleanup(String cleanupTaskId, int intervalMinutes) {
RScheduledExecutorService executor = redissonClient.getScheduledExecutor(SCHEDULED_EXECUTOR + "cleanup");
executor.scheduleAtFixedRate(() -> {
try {
doDataCleanup();
} catch (Exception e) {
log.error("数据清理任务失败", e);
}
}, 0, intervalMinutes, TimeUnit.MINUTES);
}
private void doDataCleanup() {
// 清理逻辑
}
}
使用场景汇总
| 场景 | 推荐功能 | 说明 |
|---|---|---|
| 防止并发扣库存 | 可重入锁 | 锁住库存 key |
| 接口限流 | 信号量 | 限制并发数 |
| 缓存防穿透 | 布隆过滤器 | 快速判断是否存在 |
| 订单状态同步 | Pub/Sub | 状态变更通知 |
| 任务调度 | 分布式调度 | 定时执行任务 |
| 计数器 | 原子 Long | 分布式自增 |
| Session 管理 | 分布式 Map | 跨服务共享 |
总结
- 分布式锁:使用可重入锁,注意锁的粒度和释放
- 分布式集合:Map、Set、List 适用于不同场景
- 分布式对象:原子操作、布隆过滤器很有用
- 同步器:Semaphore、CountDownLatch 用于协调
- 消息:Pub/Sub 用于事件通知
持续更新中...