Redisson + Lettuce 在 Spring Boot 中的最佳实践方案,本文从推荐理由、配置维护、代码使用示例、代码验证、总结、问答、实施建议等方面详细阐述。
主流Java Redis客户端(Jedis、Lettuce、Redisson)差异对比-CSDN博客
目录
[1. 为什么推荐 Redisson + Lettuce 共存?](#1. 为什么推荐 Redisson + Lettuce 共存?)
[2. 配置与维护建议](#2. 配置与维护建议)
[3. 代码中使用示例](#3. 代码中使用示例)
[1. Lettuce 的使用方式(通过 Spring Data Redis)](#1. Lettuce 的使用方式(通过 Spring Data Redis))
[2. Redisson 的使用方式(注入 RedissonClient)](#2. Redisson 的使用方式(注入 RedissonClient))
[4. 验证 Lettuce 作为默认客户端](#4. 验证 Lettuce 作为默认客户端)
[5. 总结对比](#5. 总结对比)
[6. FAQ](#6. FAQ)
[7. 最终实施建议](#7. 最终实施建议)
1. 为什么推荐 Redisson + Lettuce 共存?
维度 | Lettuce 负责 | Redisson 负责 | 共存优势 |
---|---|---|---|
功能定位 | 基础 KV 操作/Session 管理 | 分布式锁/布隆过滤器/分布式集合 | 避免功能重叠,各司其职 |
性能优化 | 高并发读写(毫秒级响应) | 分布式场景下的原子操作 | Lettuce 处理高频基础操作,Redisson 专注复杂分布式逻辑 |
资源开销 | 轻量级连接(单连接多路复用) | 分布式对象管理 | 避免 Redisson 的 15MB+ 包体积影响基础操作性能 |
生态整合 | Spring Boot 默认集成 | 分布式架构扩展 | 即用 Spring Data Redis 标准 API,又享分布式能力 |
运维复杂度 | 自动连接管理 | 分布式状态维护 | 隔离基础连接和分布式组件的故障域 |
典型场景:
用户会话管理(Lettuce) + 订单分布式锁(Redisson)
商品缓存读取(Lettuce) + 秒杀库存扣减(Redisson 分布式原子操作)
基础数据存储(Lettuce) + 实时推荐布隆过滤器(Redisson)
2. 配置与维护建议
application.yml文件
放在 src/main/resources/ 下
如果是application.properties文件,配置一样的,只是需要按照.properties文件格式进行排版
java
# application.yml
spring:
data:
redis:
# Lettuce 基础配置 (Spring Boot 自动装配)
host: redis-primary
port: 6379
password: pass123
lettuce:
pool:
max-active: 16 # 生产环境建议 16-64
max-idle: 8
min-idle: 4
# Redisson 独立配置,单独创建一个yaml放在 src/main/resources/ 下 (不共享连接池,推荐用 yaml)
redisson:
config: classpath:redisson-config.yaml
redisson.yaml
放在 src/main/resources/ 下
XML
# redisson-config.yaml (单独配置文件)
#单机节点配置样例
singleServerConfig:
address: "redis://127.0.0.1:6379"
password: "123456"
database: 11
timeout: 5000
connectionPoolSize: 256 #单个 Redis 节点的最大连接数(默认值:64;提高此值可支持更高的并发请求,但不要超过 Redis 服务端限制)
connectionMinimumIdleSize: 64 #单个 Redis 节点最小空闲连接数(默认值:24;忽略idleConnectionTimeout配置,一直保持活跃的连接数,通常设为 connectionPoolSize 的 1/4 左右)
idleConnectionTimeout: 3000 #空闲连接超时时间(默认值:10000毫秒,连接在空闲多久后会被关闭并释放资源,太短会导致频繁创建/销毁连接;太长会占用更多内存)
pingConnectionInterval: 2000 #心跳间隔时间(默认值:0-不发心跳,用于维持连接活跃,推荐设为比 Redis服务端空闲连接超时的时间略短)
#集群配置样例
#clusterServersConfig:
# nodeAddresses:
# - "redis://192.168.0.1:6379"
# - "redis://192.168.0.2:6379"
# - "redis://192.168.0.3:6379"
# password: "your-cluster-password" # 如果有密码保护
# database: 5 # 默认为 0,集群模式下通常忽略该参数
# timeout: 5000 # 连接超时时间(毫秒)
# connectionPoolSize: 256 # 每个节点的最大连接数
# connectionMinimumIdleSize: 64 # 每个节点最小空闲连接数
# idleConnectionTimeout: 3000 # 空闲连接超时时间(毫秒)
# pingConnectionInterval: 2000 # 心跳间隔(毫秒),用于维持连接活跃
pom依赖
排除掉jedis依赖
XML
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<version>2.7.4</version>
<exclusions>
<exclusion>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</exclusion>
</exclusions>
</dependency>
维护建议:
-
连接隔离:Lettuce 连接业务Redis,Redisson 连接分布式专用Redis
-
监控分离:
-
Lettuce:监控连接池利用率 (
spring.data.redis.lettuce.pool.*
) -
Redisson:监控分布式对象状态 (
RedissonClient.getNodesGroup().pingAll()
)
-
-
版本控制:
XML// build.gradle ext { lettuceVersion = '6.2.6.RELEASE' redissonVersion = '3.23.2' } dependencies { implementation "org.springframework.boot:spring-boot-starter-data-redis" implementation "org.redisson:redisson-spring-boot-starter:${redissonVersion}" // 排除潜在冲突 configurations.all { exclude group: 'io.lettuce', module: 'lettuce-core' exclude group: 'org.redisson', module: 'redisson-spring-data-*' } }
3. 代码中使用示例
1. Lettuce 的使用方式(通过 Spring Data Redis)
注入 RedisTemplate 或 StringRedisTemplate 即可:
java
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
@Service
public class CacheService {
private final StringRedisTemplate redisTemplate;
public CacheService(StringRedisTemplate redisTemplate) {
this.redisTemplate = redisTemplate;
}
public void set(String key, String value) {
redisTemplate.opsForValue().set(key, value);
}
public String get(String key) {
return redisTemplate.opsForValue().get(key);
}
}
2. Redisson 的使用方式(注入 RedissonClient)
java
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Service;
import java.util.concurrent.TimeUnit;
@Service
public class DistributedLockService {
private final RedissonClient redissonClient;
public DistributedLockService(RedissonClient redissonClient) {
this.redissonClient = redissonClient;
}
public void acquireLock(String lockKey) {
RLock lock = redissonClient.getLock(lockKey);
boolean isLocked = false;
try {
isLocked = lock.tryLock(10, 30, TimeUnit.SECONDS);
if (isLocked) {
// 执行业务逻辑
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
if (isLocked && lock.isHeldByCurrentThread()) {
lock.unlock();
}
}
}
}
java
// 基础操作使用 Lettuce (通过 Spring Data Redis)
@RestController
public class CacheController {
@Autowired
private StringRedisTemplate redisTemplate; // 基于Lettuce
@PostMapping("/user")
public void saveUser(@RequestBody User user) {
// 基础KV操作
redisTemplate.opsForValue().set("user:"+user.getId(),
objectMapper.writeValueAsString(user));
// Session管理 (Spring Session自动使用Lettuce)
redisTemplate.opsForHash().put("session:active",
session.getId(), user.getId());
}
}
// 分布式功能使用 Redisson
@Service
public class OrderService {
@Autowired
private RedissonClient redisson; // 独立注入
public void processOrder(String orderId) {
RLock lock = redisson.getLock("order_lock:" + orderId);
try {
lock.lock(10, TimeUnit.SECONDS); // 分布式锁
RBloomFilter<String> bloomFilter = redisson.getBloomFilter("processed_orders");
bloomFilter.tryInit(1000000L, 0.01); // 布隆过滤器
if (!bloomFilter.contains(orderId)) {
// 分布式集合操作
RSet<String> processingSet = redisson.getSet("processing_orders");
processingSet.add(orderId);
// ...业务逻辑
bloomFilter.add(orderId);
}
} finally {
lock.unlock();
}
}
}
4. 验证 Lettuce 作为默认客户端
java
@SpringBootTest
public class ClientVerificationTest {
@Autowired
private RedisConnectionFactory connectionFactory;
@Test
public void verifyLettuceClient() {
// 验证1:检查连接工厂类型
assertTrue(connectionFactory instanceof LettuceConnectionFactory);
// 验证2:获取原生连接对象
try (RedisConnection conn = connectionFactory.getConnection()) {
LettuceConnection lettuceConn = (LettuceConnection) conn;
System.out.println("Lettuce version: " +
lettuceConn.getNativeConnection().getOptions().getVersion());
}
// 验证3:查看依赖树 (Gradle)
// ./gradlew dependencies | grep lettuce
// 应包含: io.lettuce:lettuce-core:6.x.x
}
}
java
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
//验证是否使用的是 Lettuce 而非 Jedis
@Component
public class RedisClientChecker {
private final RedisConnectionFactory redisConnectionFactory;
public RedisClientChecker(RedisConnectionFactory redisConnectionFactory) {
this.redisConnectionFactory = redisConnectionFactory;
}
@PostConstruct
public void checkClient() {
String clientType = redisConnectionFactory.getClass().getName();
if (clientType.contains("Lettuce")) {
System.out.println("当前 Redis 客户端为 Lettuce");
} else if (clientType.contains("Jedis")) {
System.out.println("当前 Redis 客户端为 Jedis,请检查依赖排除");
} else {
System.out.println("当前 Redis 客户端未知:" + clientType);
}
}
}
5. 总结对比
对比维度 | 纯 Lettuce 方案 | 纯 Redisson 方案 | Lettuce+Redisson 组合方案 |
---|---|---|---|
基础操作性能 | ⭐⭐⭐ (10万+ QPS) | ⭐⭐ (6万 QPS) | ⭐⭐⭐ (Lettuce处理基础) |
分布式能力 | ❌ 需自行实现 | ⭐⭐⭐ 开箱即用 | ⭐⭐⭐ (Redisson负责) |
资源开销 | ⭐⭐⭐ (低内存/CPU) | ⭐ (15MB+ JAR/高内存) | ⭐⭐ (隔离关键组件) |
配置复杂度 | ⭐ (Spring Boot自动配置) | ⭐⭐ (需独立配置) | ⭐⭐ (双配置但清晰隔离) |
架构扩展性 | ⭐⭐ (需定制分布式逻辑) | ⭐⭐ (强分布式弱基础) | ⭐⭐⭐ (按需扩展) |
推荐场景 | 纯缓存/会话管理 | 强分布式系统 | 企业级应用最佳实践 |
6. FAQ
❓ 是否可以在 application.yml 中直接配置 Redisson?
可以,但不推荐。Redisson 的配置项较多,放在 redisson.yaml 更清晰。
❓ Redisson 会影响 Lettuce 的连接吗?
不会。只要它们使用的是不同的连接池和配置,互不影响。
❓ Redisson 和 Lettuce 是否会重复建立连接?
可能会,但这是可控的。你可以将 Redisson 配置为共享连接池,或者调整其连接池大小以适应系统负载。
❓ SpringBoot中使用Lettuce +Redisson 时,一般会把那个自动装配关闭,等使用时,在手动实例化比较好?
✅ 场景一:推荐默认启用自动装配(适用于大多数项目)
✔️ 推荐方式:
Lettuce:保持 Spring Boot 的自动装配(spring-boot-starter-data-redis)
Redisson:保持 redisson-spring-boot-starter 的自动装配
📌 原因:
自动装配简化开发:Spring Boot 自动完成配置、初始化、连接池管理等繁琐工作。
生产级配置支持良好:Spring Boot 和 Redisson Starter 都提供了丰富的配置项(YAML/Properties),可满足大部分场景。
资源统一管理:便于与 Spring 的生命周期、健康检查、监控集成。
✅ 适用场景:
普通业务系统
不需要多个 Redis 实例或复杂隔离的项目
开发效率优先于极致性能调优
✅ 场景二:建议手动实例化(高级用法)
⚠️ 当你有以下需求时,建议关闭自动装配:
|------------------------------------------|-----------|
| 需求 | 是否建议手动实例化 |
| 使用多个 Redis 实例(如主从、跨集群) | ✅ 是 |
| 对 Redisson 或 Lettuce 的连接池进行细粒度控制(如动态扩缩容) | ✅ 是 |
| 需要自定义连接池参数、SSL、超时策略等 | ✅ 是 |
| 需要与已有组件兼容(如旧版 SDK) | ✅ 是 |
- 禁用 Redisson 自动装配(不使用 starter)
XML
<!-- 改为使用 redisson-core 而非 redisson-spring-boot-starter -->
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>3.23.5</version>
</dependency>
然后手动配置 RedissonClient:
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://127.0.0.1:6379")
.setConnectionPoolSize(64)
.setIdleConnectionTimeout(10000);
return Redisson.create(config);
}
}
- Lettuce 可继续使用自动装配
除非你需要多个 Redis 数据源,否则无需替换 Spring Data Redis 提供的 RedisTemplate。
7. 最终实施建议
-
组件边界:
-
部署拓扑:
+------------------+ +-------------------+ | Spring Boot App | | Redis Cluster | | | | | | +------------+ | | +---------------+ | | | Lettuce |-----> | | Business Node | | | +------------+ | | +---------------+ | | | | | | +------------+ | | +---------------+ | | | Redisson |-----> | | Distributed | | | +------------+ | | | Node | | | | | +---------------+ | +------------------+ +-------------------+
-
升级路径:
-
新项目:直接采用组合方案
-
旧项目迁移:
-
组合方案核心价值:在享受 Spring 生态便捷性的同时,获得企业级分布式能力,且通过资源隔离保障基础服务性能稳定性。