Redisson 常用技巧

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 跨服务共享

总结

  1. 分布式锁:使用可重入锁,注意锁的粒度和释放
  2. 分布式集合:Map、Set、List 适用于不同场景
  3. 分布式对象:原子操作、布隆过滤器很有用
  4. 同步器:Semaphore、CountDownLatch 用于协调
  5. 消息:Pub/Sub 用于事件通知

持续更新中...

相关推荐
java干货1 小时前
明明删了数据,磁盘却满了?
java
之歆1 小时前
HA 高可用集群指南
java·开发语言
tod1132 小时前
深入理解 Redis 事务:从原理到实践的完整解析
数据库·redis·缓存
CHANG_THE_WORLD2 小时前
指针入门一
java·前端·网络
时艰.2 小时前
订单系统读写分离方案设计与实现
java
014-code2 小时前
MySQL 事务隔离级别
java·数据库·mysql
hrhcode3 小时前
【Netty】三.ChannelPipeline与ChannelHandler责任链深度解析
java·后端·spring·springboot·netty
Re.不晚3 小时前
Redis——哨兵机制
数据库·redis·bootstrap
invicinble3 小时前
关于学习技术栈的思考
java·开发语言·学习