https://www.toutiao.com/article/7543900720497246760/

Spring Boot 分布式利器:Redisson 升级与实战指南
2025-08-29 15:15·云中欢快游弋的龙
作品声明:内容由AI生成
Spring Boot 分布式利器:Redisson 升级与实战指南
目标:升级 Redisson 并在 Spring Boot 应用中构建一套稳定、可扩展的分布式处理方案,覆盖分布式锁、异步/流式处理与集群优化,提升分布式处理能力与可靠性。

✨ 为什么升级 Redisson?
Redisson 是功能丰富的 Redis 客户端,封装了分布式锁、分布式集合、队列、延迟队列、分布式调度、Reactive API 等常用分布式原语。升级到较新的版本(例如 3.17.x 及以上)可以获得:

更好的性能与稳定性
更完整的集群支持与错误修复
新特性(Reactive API、更多数据结构与优化配置)
更好的与 Spring Boot 不同版本的兼容性
依赖管理与基础配置(Maven + application.yml)
示例依赖(按 Spring Boot 版本选择兼容版本):

<dependency>
    <groupId>org.redisson</groupId>
    <artifactId>redisson-spring-boot-starter</artifactId>
    <version>3.17.7</version> <!-- 根据实际情况选择或升级到最新 -->
</dependency>

典型 application.yml(支持集群/单机/哨兵):

spring:
  redis:
    cluster:
      nodes:
        - 192.168.1.11:7000
        - 192.168.1.12:7000
        - 192.168.1.12:7001
      max-redirects: 3
    password: your_password_here
    timeout: 60000ms

redisson:
  threads: 8
  nettyThreads: 16
  clusterServersConfig:
    masterConnectionMinimumIdleSize: 16
    masterConnectionPoolSize: 32
    slaveConnectionMinimumIdleSize: 16
    slaveConnectionPoolSize: 64
    idleConnectionTimeout: 10000
    timeout: 3000
    readMode: "SLAVE"
    subscriptionMode: "MASTER"
    scanInterval: 2000

RedissonClient Java 配置(按需切换模式)

@Configuration
public class RedissonConfig {

    @Autowired
    private RedisConfigProperties redisConfigProperties; // 自定义配置类

    @Bean(destroyMethod = "shutdown")
    public RedissonClient redissonClient() throws IOException {
        Config config = new Config();
        // 集群模式示例
        config.useClusterServers()
                .setScanInterval(2000)
                .setPassword(redisConfigProperties.getPassword())
                .addNodeAddress(redisConfigProperties.getClusterNodes().toArray(new String[0]));
        // 根据条件可以选择单机或哨兵配置
        return Redisson.create(config);
    }
}

分布式锁:类型、注解与最佳实践
锁类型与适用场景
锁类型

适用场景

特点

RLock(可重入锁)

大多数互斥场景

支持重入、看门狗自动续期、默认超时 30s

FairLock(公平锁)

需要按请求顺序分配锁

防止饥饿,但性能略差

RReadWriteLock(读写锁)

读多写少场景

读并发、写互斥

MultiLock(联锁)

多个资源需同时加锁

所有关联锁都成功才算成功

RedLock

要求极高可靠性(慎用)

在多个独立 Redis 实例上多数节点获锁才成功(复杂且有争议)

注解式分布式锁(示例)
自定义注解:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface DistributedLock {
    String value(); // 锁 key
    long leaseTime() default -1; // 持锁时间,-1 启用看门狗
    long waitTime() default -1; // 等待时间,-1 不等待
}

切面实现(关键逻辑):

@Aspect
@Component
@Slf4j
public class DistributedLockAspect {

    @Autowired
    private RedissonClient redissonClient;

    @Around("@annotation(distributedLock)")
    public Object around(ProceedingJoinPoint joinPoint, DistributedLock distributedLock) throws Throwable {
        String lockKey = distributedLock.value();
        RLock lock = redissonClient.getLock(lockKey);
        boolean locked = false;
        try {
            if (distributedLock.waitTime() == -1) {
                locked = lock.tryLock(0, distributedLock.leaseTime(), TimeUnit.SECONDS);
            } else {
                locked = lock.tryLock(distributedLock.waitTime(), distributedLock.leaseTime(), TimeUnit.SECONDS);
            }
            if (locked) {
                log.debug("获取分布式锁成功,key: {}", lockKey);
                return joinPoint.proceed();
            } else {
                throw new RuntimeException("获取分布式锁失败,key: " + lockKey);
            }
        } finally {
            if (locked && lock.isHeldByCurrentThread()) {
                lock.unlock();
                log.debug("释放分布式锁成功,key: {}", lockKey);
            }
        }
    }
}

工具类封装(示例)

@Component
@Slf4j
public class RedissonLockUtil {

    @Autowired
    private RedissonClient redissonClient;

    public <T> T executeWithLock(String key, long waitTime, long leaseTime, TimeUnit unit, Supplier<T> supplier) {
        RLock lock = redissonClient.getLock(key);
        try {
            boolean locked = lock.tryLock(waitTime, leaseTime, unit);
            if (!locked) {
                throw new RuntimeException("Acquire lock failed for key: " + key);
            }
            try {
                return supplier.get();
            } finally {
                if (lock.isHeldByCurrentThread()) {
                    lock.unlock();
                }
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            throw new RuntimeException("Lock interrupted", e);
        }
    }

    public void executeWithLock(String key, Runnable task) {
        executeWithLock(key, -1, -1, TimeUnit.SECONDS, () -> { task.run(); return null; });
    }
}

使用模式示例
注解方式


@DistributedLock(value = "order:lock:#{#orderId}", leaseTime = 30)
public void processOrder(String orderId) { ... }
工具类方式
redissonLockUtil.executeWithLock("order:lock:" + orderId, () -> { ... });
编程式(显式)
RLock lock = redissonClient.getLock("order:lock:" + orderId);
try {
    if (lock.tryLock(5, 30, TimeUnit.SECONDS)) { ... }
} finally {
    if (lock.isHeldByCurrentThread()) lock.unlock();
}

关键注意事项
锁粒度要尽可能细:order:lock:12345 优于 order:lock
在 finally 中仅当 lock.isHeldByCurrentThread() 为真时释放
若未指定 leaseTime(或设置 -1)将启用看门狗自动续期;显式指定 leaseTime 则看门狗失效
避免在锁内执行长阻塞/IO 操作,防止占用资源与阻塞续期逻辑
在 Redis 集群场景下,若需要跨 key 原子性需保证 keys 落在同一 slot(使用 {} 模式)

⚡ 异步 / 流处理(队列、延迟队列、Reactive)
分布式阻塞队列(生产/消费)
RBlockingQueue<String> queue = redissonClient.getBlockingQueue("myTaskQueue");

// 生产者
queue.put("Task 1");

// 消费者(阻塞)
String task = queue.take();
多个实例可并行消费,适用于工作队列场景。
延迟队列(定时/延迟任务)
RDelayedQueue<String> delayedQueue = redissonClient.getDelayedQueue(redissonClient.getBlockingQueue("myDelayedQueue"));
delayedQueue.offer("Delayed Task", 5, TimeUnit.MINUTES);
适合非精确到毫秒的定时/重试场景,另外注意处理重复消费与幂等。
Reactive 异步接口(非阻塞)
@Autowired
private RedissonReactiveClient redissonReactiveClient;

public Mono<String> reactiveGet(String key) {
    return redissonReactiveClient.getBucket(key).get();
}

public Flux<String> reactivePubSub(String channel) {
    return redissonReactiveClient.getTopic(channel).getMessages(String.class);
}

用于高并发、异步非阻塞编程,与 Project Reactor 无缝对接。
集群架构优化(生产级建议)
连接池与通道优化

clusterServersConfig:
  masterConnectionMinimumIdleSize: 16
  masterConnectionPoolSize: 64
  slaveConnectionMinimumIdleSize: 16
  slaveConnectionPoolSize: 64
  idleConnectionTimeout: 10000
  connectTimeout: 10000
  timeout: 3000
  retryAttempts: 3
  retryInterval: 1500

根据并发、QPS 调整连接池大小,避免过大导致 Redis 内存/文件描述符压力。
读写分离与负载均衡

clusterServersConfig:
  readMode: "SLAVE" # 将读分流到从节点
  loadBalancer: !<org.redisson.connection.balancer.RoundRobinLoadBalancer> {}

读多写少场景显著提高吞吐量,但需权衡数据一致性。
监控与告警
启用 Redis 慢查询日志
监控 Redisson 连接池、等待线程数、命令失败率
Redis 节点:内存、CPU、连接数告警阈值
建议接入 Prometheus / Grafana 或云厂商监控系统
性能调优与排障清单
网络与传输层
在 Linux 可考虑 Netty EPOLL(transportMode: EPOLL)提升性能
序列化(Codec)
根据需求选择:JsonJacksonCodec(可读)、FstCodec(高性能),权衡体积与速度
避免长时间锁持有
尽量把耗时操作移出锁内
集群 key slot 注意
若业务涉及多个 key 的原子操作,注意使用 {} 强制到同一 slot(例如:my:{id}:lock)
时钟同步
确保服务器时钟同步(NTP),避免与超时/lease 时间相关的异常
调试建议
捕获并分析慢命令(SLOWLOG)
在测试环境进行压力测试(并发、网络抖动、Redis 节点故障场景)
✅ 生产部署与验证建议(Checklist)
检查 Redisson 与 Spring Boot 的兼容版本
在预发布环境做压力测试:并发场景、锁竞争、队列吞吐
演练 Redis 节点故障切换(模拟单点失败、网络分区)
配置监控并设定告警规则
对关键场景实现幂等与重试策略
代码审查锁使用点,尽量集中管理(注解或工具类)
扩展功能与进阶探索
Redisson 还支持分布式集合、原子数、分布式调度(Cron)、Redisson 的 Map/Set 结构、分布式信号量/栅栏等。可基于这些构建更复杂的协调与调度系统,例如分布式限流、全局定时任务、分布式 barrier 等。

总结
成功升级 Redisson 并落地到生产环境,关键要点是:

选对版本并确保兼容性;
合理配置 RedissonClient(线程、连接池、读写策略);
对分布式锁的使用做规范(粒度、超时、释放)并封装成注解/工具类,减少业务误用;
使用队列/延迟队列/Reactive API 构建异步、解耦的处理链路;
在集群环境做针对性优化,并建立完善的监控与演练流程

文档更新时间: 2025-09-12 08:30   作者:admin