一.背景
最近在搭建一个新项目,本着有新用新的原则,项目选择到了jdk17+SpringBoot3.4。但是在测试Redis连接的时候却遇到了以下问题:
redis连不上了。于是我先去检查了配置文件的连接信息,发现没问题;再去检查配置类:
也没发现问题。并且我去启动了以前用SpringBoot2.X的老项目,发现同样的配置下,以前的老项目就能成功连上Redis。那这下就大概可以确定原因了:SpringBoot3.4版本下,引用的spring-boot-starter-data-redis可能有点毛病。
二.发现问题
1.问题发现
既然可能是版本问题,那就只能去github上看看了
果然也有其它人遇到了相同的问题,不过还好这个问题已经被解决了
翻译一下就是:
Lettuce驱动程序版本在Spring Data和Spring Boot版本之间发生了变化,这些版本改变了握手行为。我建议您通过clientOptions.builder(). protocolversion (ProtocolVersion.RESP2).build()来配置LettuceClientConfiguration.clientOptions,来强制RESP2处理,这样你就不会遇到HELLO错误,并且将使用AUTH命令来应用身份验证。
看起来Lettuce客户端已经通过redis/ Lettuce #3035修复了6.5版本的问题。
在任何情况下,这都是驱动程序的问题。
据此可以得到两种解决方案:
(1)手动配置LettuceClientConfiguration.clientOptions的protocolversion
(2)将Lettuce升级到6.5
2.问题验证
我的“spring-boot-starter-data-redis”版本是跟着springboot版本走的,也就是3.4.0
接下来看一下“spring-boot-starter-data-redis”提供的lettuce依赖
可以看,到lettuce依赖版本默认是6.4.1,而不是已经解决bug的6.5。接下来对程序debug验证一下lettuce版本为6.4.1时,LettuceClientConfiguration.clientOptions的protocolversion
可以看到,Spring为我们自动配置的RedisConnectionFactory中,clientOptions的protocolVersion属性为null,没有被设置为RESP2。
三.解决方案
1.手动配置LettuceClientConfiguration.clientOptions的protocolversion
我们不使用Spring为我们自动配置的RedisConnectionFactory,而是自己配置一个LettuceConnectionFactory交给IOC容器管理。在配置LettuceConnectionFactory时通过配置ClientOptions的protocolVersion为RESP2,来解决连接bug。
(1)配置代码
自己配置LettuceConnectionFactory的话还需要引入外部连接池依赖
<dependency><groupId>org.apache.commons</groupId><artifactId>commons-pool2</artifactId></dependency>
/*** 配置线程池连接工厂LettuceConnectionFactory* @return*/@Beanpublic LettuceConnectionFactory lettuceConnectionFactory(){// redis配置RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration(host, port);redisStandaloneConfiguration.setDatabase(dataBase);redisStandaloneConfiguration.setPassword(password);// 连接池配置GenericObjectPoolConfig genericObjectPoolConfig = new GenericObjectPoolConfig();genericObjectPoolConfig.setMinIdle(minIdle);genericObjectPoolConfig.setMaxIdle(maxIdle);genericObjectPoolConfig.setMaxWait(Duration.ofDays(maxWait));genericObjectPoolConfig.setMaxTotal(maxActive);// ClientOptions配置ClientOptions clientOptions = ClientOptions.builder().protocolVersion(ProtocolVersion.RESP2).build();// redis客户端配置LettucePoolingClientConfiguration.LettucePoolingClientConfigurationBuilderbuilder = LettucePoolingClientConfiguration.builder().clientOptions(clientOptions).commandTimeout(Duration.ofMillis(timeOut));builder.poolConfig(genericObjectPoolConfig);LettuceClientConfiguration lettuceClientConfiguration = builder.build();return new LettuceConnectionFactory(redisStandaloneConfiguration,lettuceClientConfiguration);}
(2)启动验证
可以看到此时注入进来的RedisConnectionFactory就是我们自己配置的LettuceConnectionFactory,其ClientOptions的protocolVersion属性为RESP2。Redis可以被正常连接。
2.将Lettuce升级到6.5
这种方法就比较简单粗暴了,既然“spring-boot-starter-data-redis”提供的lettuce依赖版本为6.4,那我们就不用它提供的了,自己引入版本为6.5的lettuce依赖。
(1)配置代码
<!--redis--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId><exclusions><exclusion><groupId>io.lettuce</groupId><artifactId>lettuce-core</artifactId></exclusion></exclusions></dependency><!--lettuce--><dependency><groupId>io.lettuce</groupId><artifactId>lettuce-core</artifactId><version>${lettuce.version}</version></dependency><!--外部连接池--><dependency><groupId>org.apache.commons</groupId><artifactId>commons-pool2</artifactId></dependency>
其中lettuce.version是6.5.0.RELEASE。最下面的“commons-pool2”是如果要自己配置LettuceConnectionFactory才需要引入,也就是方案一要用到,这里没有删掉。
(2)启动验证
IOC容器中的Spring为我们自动配置的RedisConnectionFactory的clientOptions.protocolVersion仍然是null,但是此时Redis已经可以正常连接上了,说明Lettuce 6.5.0已经解决了认证连接bug。