lettuce-reactive 在 spring boot 中不自动启用响应式支持,因自动配置仅在引入 spring-boot-starter-data-redis-reactive 且未手动配置连接工厂时注入 reactiveredisconnectionfactory;否则默认使用同步工厂,导致 unsupportedoperationexception。

为什么 lettuce-reactive 在 Spring Boot 里不自动启用响应式支持
Spring Boot 2.0+ 默认用 Lettuce 作为 Redis 客户端,但 LettuceConnectionFactory 默认创建的是同步连接;即使你写了 ReactiveRedisTemplate,底层若没配对,运行时会抛 java.lang.UnsupportedOperationException: This method is not supported in reactive mode。
根本原因:Spring Boot 的自动配置只在检测到 spring-boot-starter-data-redis-reactive 依赖且未显式配置连接工厂时,才注入响应式专用的 ReactiveRedisConnectionFactory。
- 检查是否引入了
spring-boot-starter-data-redis-reactive(不是spring-boot-starter-data-redis) - 确认 Maven 中没有同时引入两个 starter——冲突会导致自动配置失效
- 如果手动定义了
@Bean ReactiveRedisTemplate,但没配ReactiveRedisConnectionFactory,Spring 会 fallback 到同步工厂,此时调用opsForValue().get()返回的是Mono,但内部实际走同步阻塞逻辑,压测时会暴露线程池耗尽问题
如何正确配置 ReactiveRedisConnectionFactory
别依赖“自动就对”,尤其在多环境或自定义连接参数时。最稳的方式是显式声明 ReactiveRedisConnectionFactory Bean。
关键点:必须用 LetTuceClientConfigurationBuilder 构建客户端配置,并传给 ReactiveRedisConnectionFactory 实例,否则超时、SSL、集群等配置可能被忽略。
- 用
RedisStandaloneConfiguration或RedisClusterConfiguration配地址和密码,不要直接 newRedisConfiguration - 连接池必须用
ClientResources.create()创建资源,否则ReactiveRedisConnectionFactory无法复用连接,每次操作新建连接 - 超时设置要分层:连接超时(
connectTimeout)、命令超时(commandTimeout),后者需通过ClientOptions.builder().timeoutOptions(TimeoutOptions.enabled())显式开启
示例片段:
你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
@Bean
public ReactiveRedisConnectionFactory redisConnectionFactory() {
RedisStandaloneConfiguration config = new RedisStandaloneConfiguration("localhost", 6379);
config.setPassword(RedisPassword.of("pwd"));
LettuceClientConfiguration clientConfig = LettuceClientConfiguration.builder()
.clientOptions(ClientOptions.builder()
.timeoutOptions(TimeoutOptions.enabled())
.build())
.commandTimeout(Duration.ofSeconds(3))
.build();
return new LettuceConnectionFactory(config, clientConfig);
}
ReactiveRedisTemplate 常见误用与类型陷阱
ReactiveRedisTemplate 的泛型不是摆设:键/值序列化器决定你存进去的是字节还是结构化数据,错配会导致 SerializationException 或读出来全是乱码。
典型现象:用 StringRedisTemplate 存的 key,用 ReactiveRedisTemplate<object object></object> 读,结果 get("k1") 返回 Mono.empty() —— 实际是反序列化失败后静默丢弃。
- 统一用
RedisSerializationContext.StringString()配置,确保 key 和 value 都走 UTF-8 字符串编解码 - 避免混用
ReactiveRedisTemplate<string string></string>和ReactiveRedisTemplate<string person></string>操作同一个 key 空间 - 注意
opsForHash().entries()返回Mono<map>></map>,不是Flux;想流式处理 hash 所有 field-value,得用opsForHash().values()+flatMapMany
连接泄漏和背压没处理的典型表现
响应式不是“加个 Mono 就完事”。Lettuce 的响应式连接是共享的,但如果你在 flatMap 里无限制发起 Redis 请求,又没做限流或错误兜底,会出现两种崩溃点:连接数暴涨(io.lettuce.core.RedisConnectionException: Unable to connect),或下游 subscriber 被压垮(IllegalStateException: Queue is full)。
- 用
onErrorResume替代onErrorContinue,后者在 Redis 场景下容易掩盖网络抖动问题 - 批量操作优先用
opsForValue().multiGet(),别写Flux.fromIterable(keys).flatMap(key -> template.opsForValue().get(key)) - 测试阶段务必开
lettuce: debug日志,观察CommandHandler是否频繁打印Connection closed或Channel inactive
真正难调的永远不是怎么连上,而是连接什么时候该断、谁负责释放、超时后要不要重试——这些在响应式链路里全得自己拍板,框架不会替你决定。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










