1. Redisson与Spring Boot整合概述
在现代分布式系统开发中,Redis作为高性能的内存数据库已经成为标配。而Redisson作为Redis官方推荐的Java客户端,提供了比原生Jedis或Lettuce更丰富的分布式功能。我在多个生产项目中实践发现,Redisson的分布式锁、原子计数器等特性能够显著简化分布式系统开发。
Spring Boot与Redisson的整合主要有两种主流方式:
- 基于starter的自动配置方式(适合大多数标准场景)
- 自定义配置类方式(适合需要精细控制的场景)
我将通过实际项目经验,详细剖析这两种方式的实现细节、适用场景和避坑指南。无论你是刚开始接触Redisson,还是已经在使用但遇到配置问题,这篇文章都能提供可直接落地的解决方案。
2. 基于starter的自动配置方式
2.1 环境准备与依赖配置
首先需要在pom.xml中添加Redisson的Spring Boot Starter依赖。这里有个容易踩的坑:不需要同时引入spring-boot-starter-data-redis,否则会导致依赖冲突。
xml复制<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-boot-starter</artifactId>
<version>3.23.5</version>
</dependency>
版本选择建议:
- Spring Boot 2.x 使用Redisson 3.17.x+
- Spring Boot 3.x 需要Redisson 3.23.x+
2.2 YAML配置详解
在application.yml中配置Redis连接信息时,需要注意Spring Boot 2.x和3.x的配置项差异:
yaml复制# Spring Boot 3.x配置方式
spring:
data:
redis:
host: 127.0.0.1
port: 6379
password: yourpassword
database: 0
timeout: 5000
connect-timeout: 3000
# Spring Boot 2.x需要改用以下格式
spring:
redis:
host: 127.0.0.1
# 其他配置项相同
常见配置问题排查:
- 连接超时:检查connect-timeout是否设置过短(生产环境建议≥3s)
- 认证失败:确保password字段正确且Redis服务端requirepass配置匹配
- 版本不兼容:Spring Boot 3必须使用Redisson 3.23+
2.3 使用RedissonClient
自动配置完成后,可以直接注入RedissonClient使用。这里分享一个实际项目中的分布式锁最佳实践:
java复制@RestController
public class OrderController {
@Autowired
private RedissonClient redissonClient;
@PostMapping("/order")
public String createOrder() {
RLock lock = redissonClient.getLock("orderLock");
try {
// 尝试获取锁,最多等待5秒,锁自动释放时间10秒
boolean locked = lock.tryLock(5, 10, TimeUnit.SECONDS);
if(locked) {
// 业务逻辑
return "Order created";
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new RuntimeException("Acquire lock failed", e);
} finally {
if(lock.isLocked() && lock.isHeldByCurrentThread()) {
lock.unlock();
}
}
return "System busy";
}
}
关键注意事项:
- 总是使用tryLock设置明确的等待时间和自动释放时间
- 释放锁前检查当前线程是否持有锁
- 处理InterruptedException时恢复中断状态
3. 自定义配置类方式
3.1 适用场景分析
在以下情况建议使用自定义配置类:
- 需要连接多个Redis集群
- 使用Redisson的特殊功能(如SSL连接、哨兵模式等)
- 需要细粒度控制Redisson配置
3.2 完整配置示例
下面是一个支持主从模式的配置类实现:
java复制@Configuration
public class RedissonConfig {
@Value("${redis.master.host}")
private String masterHost;
@Value("${redis.slave.host}")
private String slaveHost;
@Value("${redis.port}")
private int port;
@Value("${redis.password}")
private String password;
@Bean(destroyMethod = "shutdown")
public RedissonClient redissonClient() {
Config config = new Config();
config.useMasterSlaveServers()
.setMasterAddress("redis://" + masterHost + ":" + port)
.addSlaveAddress("redis://" + slaveHost + ":" + port)
.setPassword(password)
.setConnectTimeout(5000)
.setTimeout(3000)
.setRetryAttempts(3)
.setRetryInterval(1500);
// 优化线程池配置
config.setThreads(16)
.setNettyThreads(32);
return Redisson.create(config);
}
}
配置优化技巧:
- 线程池大小建议设置为CPU核心数的2-4倍
- 连接超时(timeout)应大于网络RTT
- 重试间隔(retryInterval)建议≥1.5秒
3.3 多数据源配置
对于需要连接多个Redis集群的场景,可以采用以下方案:
java复制@Configuration
public class MultiRedissonConfig {
@Bean(name = "primaryRedisson")
@Primary
public RedissonClient primaryRedisson() {
Config config = new Config();
config.useSingleServer()
.setAddress("redis://primary-host:6379");
return Redisson.create(config);
}
@Bean(name = "secondaryRedisson")
public RedissonClient secondaryRedisson() {
Config config = new Config();
config.useClusterServers()
.addNodeAddress("redis://node1:6379", "redis://node2:6379");
return Redisson.create(config);
}
}
使用时通过@Qualifier指定注入的Bean:
java复制@Autowired
@Qualifier("secondaryRedisson")
private RedissonClient secondaryClient;
4. 性能优化与生产实践
4.1 连接池配置建议
Redisson默认使用Netty的NIO连接池,生产环境建议调整以下参数:
yaml复制spring:
data:
redis:
redisson:
config: |
singleServerConfig:
connectionPoolSize: 64 # 最大连接数
connectionMinimumIdleSize: 24 # 最小空闲连接
idleConnectionTimeout: 10000 # 空闲连接超时(ms)
4.2 序列化优化
Redisson默认使用Jackson序列化,对于高并发场景可以切换为更高效的编码器:
java复制Config config = new Config();
config.setCodec(new MsgPackJacksonCodec()); // 比JSON体积小30%
性能对比:
- JSONCodec:兼容性好,性能中等
- MsgPackJacksonCodec:二进制格式,性能高
- KryoCodec:性能最高,但需要额外依赖
4.3 监控与运维
建议通过JMX监控Redisson状态:
java复制config.setUseScriptCache(true)
.setJmxEnabled(true);
关键监控指标:
- 活跃连接数
- 命令延迟百分位
- 内存使用情况
5. 常见问题解决方案
5.1 连接泄漏排查
现象:Redis连接数持续增长不释放
排查步骤:
- 检查所有RLock是否都有对应的unlock调用
- 使用Redisson的JMX监控查看连接状态
- 检查是否有长时间阻塞的Redis操作
5.2 性能瓶颈分析
当发现Redis操作变慢时:
- 使用slowlog get命令查看慢查询
- 检查网络延迟
- 评估大Key和热Key影响
5.3 高可用方案
生产环境推荐配置:
java复制config.useSentinelServers()
.setMasterName("mymaster")
.addSentinelAddress("redis://sentinel1:26379")
.setCheckSentinelsList(false)
.setDatabase(0);
关键配置项:
- sentinel节点至少配置3个
- setCheckSentinelsList(false)避免启动时检查所有sentinel
- 合理设置failover超时时间
在实际项目中,我遇到过一个典型场景:使用Redisson的分布式锁实现秒杀功能时,最初没有正确设置锁的自动释放时间,导致系统在高并发下出现死锁。通过添加合理的tryLock超时和leaseTime参数解决了这个问题。这也提醒我们,分布式锁的使用必须考虑各种边界条件。
