Redisson + Lettuce 在 Spring Boot 中的最佳实践方案

Redisson + Lettuce 在 Spring Boot 中的最佳实践方案,本文从推荐理由、配置维护、代码使用示例、代码验证、总结、问答、实施建议等方面详细阐述。

主流Java Redis客户端(Jedis、Lettuce、Redisson)差异对比-CSDN博客

目录

[1. 为什么推荐 Redisson + Lettuce 共存?](#1. 为什么推荐 Redisson + Lettuce 共存?)

[2. 配置与维护建议](#2. 配置与维护建议)

application.yml文件

redisson.yaml

pom依赖

[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>

维护建议

  1. 连接隔离:Lettuce 连接业务Redis,Redisson 连接分布式专用Redis

  2. 监控分离

    • Lettuce:监控连接池利用率 (spring.data.redis.lettuce.pool.*)

    • Redisson:监控分布式对象状态 (RedissonClient.getNodesGroup().pingAll())

  3. 版本控制

    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) | ✅ 是 |

  1. 禁用 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);
    }
}
  1. Lettuce 可继续使用自动装配

除非你需要多个 Redis 数据源,否则无需替换 Spring Data Redis 提供的 RedisTemplate。

7. 最终实施建议
  1. 组件边界

  2. 部署拓扑

    复制代码
    +------------------+     +-------------------+
    |  Spring Boot App |     |  Redis Cluster    |
    |                  |     |                   |
    |  +------------+  |     | +---------------+ |
    |  | Lettuce    |-----> | | Business Node | |
    |  +------------+  |     | +---------------+ |
    |                  |     |                   |
    |  +------------+  |     | +---------------+ |
    |  | Redisson   |-----> | | Distributed   | |
    |  +------------+  |     | |   Node        | |
    |                  |     | +---------------+ |
    +------------------+     +-------------------+
  3. 升级路径

    • 新项目:直接采用组合方案

    • 旧项目迁移:

组合方案核心价值:在享受 Spring 生态便捷性的同时,获得企业级分布式能力,且通过资源隔离保障基础服务性能稳定性。

相关推荐
阿昌喜欢吃黄桃几秒前
mac安装mvnd结合idea
java·maven·idea·编译·打包·mvnd·编译打包
羊小猪~~19 分钟前
数据库学习笔记(十五)--变量与定义条件与处理程序
数据库·人工智能·笔记·后端·sql·学习·mysql
墨家巨子@俏如来25 分钟前
一.干货干货!!!SpringAI入门到实战-小试牛刀
后端·springai·ai人工智能
ahhhhaaaa-26 分钟前
【AI图像生成网站&Golang】部署图像生成服务(阿里云ACK+GPU实例)
开发语言·数据仓库·人工智能·后端·阿里云·golang
码不停蹄的玄黓30 分钟前
通关JUC:Java并发工具包从入门到精通 | 深度源码解析
java·jvm·spring boot·spring·spring cloud
一只编程菜鸟32 分钟前
Java + easyexcel 新旧数据对比,单元格值标红
java·开发语言
年老体衰按不动键盘1 小时前
idea中导入maven项目的方法
java·maven·intellij-idea
jdyzzy1 小时前
从0到1做一个“任务管理系统”:Spring Boot + Vue 实战教程(含源码)
vue.js·spring boot·后端
步、步、为营1 小时前
.NET10:asp.net core mini api中的验证
java·asp.net·.net
愚农搬码1 小时前
LangChain 调用不同类型的多MCP服务
人工智能·后端