Spring Boot 3 默认使用 Lettuce 6.4.x,因 RESP3 协议协商失败(老 Redis 不支持 HELLO 命令)导致静默连接失败;需显式配置 ClientOptions.protocolVersion(ProtocolVersion.RESP2)。

Spring Boot 3 默认用 Lettuce,不是 Jedis;连不上 Redis 多数是因为 Lettuce 6.4.x 的 RESP 协议协商失败,而不是配置写错了。
为什么 Spring Boot 3 启动后报 Unable to connect to Redis 却没明显错误堆栈
这是 Lettuce 6.4.1(Spring Boot 3.4.0 默认带的版本)的一个已知行为:它在初始化连接时尝试协商 RESP3 协议,但老版本 Redis(比如 6.2 或更早)或某些云 Redis 服务(如阿里云部分实例)默认不支持或未开启 RESP3。此时 Lettuce 不抛异常,而是静默失败,最终表现为连接超时或 Unable to connect to Redis。
- debug 时能看到
LettuceClientConfiguration.clientOptions.protocolVersion是null,说明 Spring 没帮你设协议版本 - Redis 服务端日志里可能有类似
ERR unknown command 'HELLO'—— 因为HELLO是 RESP3 握手命令 - 用
redis-cli -p 6379 ping能通,不代表应用能连:客户端协议层卡住了
怎么强制 Lettuce 用 RESP2 协议(最稳的解法)
别依赖自动配置,自己注册一个带明确协议版本的 LettuceConnectionFactory Bean。
- 加连接池依赖:
org.apache.commons:commons-pool2(否则LettucePoolingClientConfiguration会报错) - 构造
ClientOptions时显式指定ProtocolVersion.RESP2 - 必须用
LettucePoolingClientConfiguration,不能只 newLettuceConnectionFactory,否则没连接池 - 密码、host、port、database 都要从配置读,别硬编码;建议封装成
@ConfigurationProperties类
示例关键代码:
@Bean
public LettuceConnectionFactory lettuceConnectionFactory(RedisProperties props) {
RedisStandaloneConfiguration config = new RedisStandaloneConfiguration();
config.setHostName(props.getHost());
config.setPort(props.getPort());
config.setDatabase(props.getDatabase());
if (props.getPassword() != null) {
config.setPassword(RedisPassword.of(props.getPassword()));
}
GenericObjectPoolConfig<?> poolConfig = new GenericObjectPoolConfig<>();
poolConfig.setMaxIdle(props.getLettuce().getPool().getMaxIdle());
poolConfig.setMinIdle(props.getLettuce().getPool().getMinIdle());
poolConfig.setMaxTotal(props.getLettuce().getPool().getMaxActive());
ClientOptions options = ClientOptions.builder()
.protocolVersion(ProtocolVersion.RESP2) // 关键!必须这行
.build();
LettuceClientConfiguration clientConfig = LettucePoolingClientConfiguration.builder()
.poolConfig(poolConfig)
.clientOptions(options)
.build();
return new LettuceConnectionFactory(config, clientConfig);
}
升级 Lettuce 到 6.5+ 能不能一劳永逸
可以,但要注意:Lettuce 6.5+ 默认 fallback 到 RESP2,不再强求 HELLO 握手。不过升级不是无痛的。
- Spring Boot 3.4.x 的
spring-boot-starter-data-redis锁死 Lettuce 6.4.1,得手动覆盖版本 - 在
pom.xml里加<lettuce-core.version>6.5.0.RELEASE</lettuce-core.version>property,并确认没其他模块传递依赖旧版 - 升级后仍建议保留
protocolVersion(ProtocolVersion.RESP2)配置 —— 显式比隐式可靠,尤其跨环境部署时 - 注意 6.5+ 对 JDK 版本有要求(最低 JDK 17),别和 Boot 3 的基线冲突
Jedis 还能不能用(不推荐但可行)
能,但 Spring Boot 3 已移除对 Jedis 的自动配置支持,你要自己配全套:连接工厂、序列化器、连接池(apache-commons-pool2)、甚至 RedisTemplate 的泛型类型绑定。
- 引入
redis.clients:jedis,排除掉 starter 自带的 lettuce - 自己 new
JedisConnectionFactory,setHost/setPort/setPassword 等 - 必须手动 setUsePool(true),否则是直连,扛不住并发
- 最大的坑是:Jedis 不支持响应式编程(
Mono/Flux),如果你项目里用了ReactiveRedisTemplate,换 Jedis 就直接废掉
除非遗留系统强依赖 Jedis 特性(比如某些 Lua 脚本调试工具链),否则别倒退。
真正容易被忽略的点是:协议版本必须在 ClientOptions 层设置,而不是靠 application.yml 里的某个 magic key;而且这个配置一旦漏掉,在本地 Redis 6.4+ 上可能正常,一上生产老版本 Redis 就挂——环境差异带来的静默故障最难查。


















