SpringBoot集成Redis后,运行一段时间后发现RedisCommandTimeoutException

背景:

在项目中引入SpringBoot的autoConfig来管理组件,在集成redis后到沙箱环境运行一段时间后,发现客户端连接redis就会出现超时。

现象:

每次调用redis执行命令的时候会出现下面这个报错:

Caused by: io.lettuce.core.RedisCommandTimeoutException: Command timed out after 1 minute(s)
at io.lettuce.core.ExceptionFactory.createTimeoutException(ExceptionFactory.java:51) ~[lettuce-core-5.1.6.RELEASE.jar!/:?]
at io.lettuce.core.LettuceFutures.awaitOrCancel(LettuceFutures.java:114) ~[lettuce-core-5.1.6.RELEASE.jar!/:?]
at io.lettuce.core.FutureSyncInvocationHandler.handleInvocation(FutureSyncInvocationHandler.java:69) ~[lettuce-core-5.1.6.RELEASE.jar!/:?]
at io.lettuce.core.internal.AbstractInvocationHandler.invoke(AbstractInvocationHandler.java:80) ~[lettuce-core-5.1.6.RELEASE.jar!/:?]
at com.sun.proxy.$Proxy143.get(Unknown Source) ~[?:?]
at org.springframework.data.redis.connection.lettuce.LettuceStringCommands.get(LettuceStringCommands.java:66) ~[spring-data-redis-2.1.8.RELEASE.jar!/:2.1.8.RELEASE]
at org.springframework.data.redis.connection.DefaultedRedisConnection.get(DefaultedRedisConnection.java:253) ~[spring-data-redis-2.1.8.RELEASE.jar!/:2.1.8.RELEASE]
at org.springframework.data.redis.connection.DefaultStringRedisConnection.get(DefaultStringRedisConnection.java:377) ~[spring-data-redis-2.1.8.RELEASE.jar!/:2.1.8.RELEASE]
at org.springframework.data.redis.core.DefaultValueOperations$1.inRedis(DefaultValueOperations.java:57) ~[spring-data-redis-2.1.8.RELEASE.jar!/:2.1.8.RELEASE]
at org.springframework.data.redis.core.AbstractOperations$ValueDeserializingRedisCallback.doInRedis(AbstractOperations.java:59) ~[spring-data-redis-2.1.8.RELEASE.jar!/:2.1.8.RELEASE]
at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:224) ~[spring-data-redis-2.1.8.RELEASE.jar!/:2.1.8.RELEASE]
at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:184) ~[spring-data-redis-2.1.8.RELEASE.jar!/:2.1.8.RELEASE]
at org.springframework.data.redis.core.AbstractOperations.execute(AbstractOperations.java:95) ~[spring-data-redis-2.1.8.RELEASE.jar!/:2.1.8.RELEASE]
at org.springframework.data.redis.core.DefaultValueOperations.get(DefaultValueOperations.java:53) ~[spring-data-redis-2.1.8.RELEASE.jar!/:2.1.8.RELEASE]
at com.anjuke.api.comboplus.scf.util.RedisUtil.get(RedisUtil.java:28) ~[classes!/:?]
at com.anjuke.api.comboplus.scf.impl.inner.BackWordServiceImpl.flushHouseRedis(BackWordServiceImpl.java:35) ~[classes!/:?]
... 10 more

排查

通过上面的报错,发现是redis超时导致的

于是,执行ping redis域名,发现是正常的。担心是不是端口有问题导致的,telnet 域名 端口,发现端口也是通的。这就很奇怪了。于是开始审视自己的代码,发现了一个不正常的情况:

下面是redis的配置

spring:
  redis:
    host: redis域名
    port: 端口
    password: password
    jedis:
      pool:
        max-active: 16
        max-wait: 5000
        max-idle: 8
        min-idle: 2

发现我配置的是jedis的客户端,但是springBoot加载的redis客户端是lettuce客户端,就怀疑是不是springboot自动注入,加载的redis客户端是不是顺序乱了导致的。

于是,去看了springboot关于redis客户端的自动注入实现:

发现springBoot在自动注入的时候会优先加载lettuce的连接工厂,这就发现配置中的配置没有发挥作用。

排查到此,也有了怀疑,为啥lettuce默认的配置会导致redis出现超时呢?于是在同事的建议下到lettuce的GitHub工程里面,看了下,lettuce是有这个bug的。看了下,发现可能是由于io底层与云平台不兼容导致,然后redis底层容器中的连接没有了,调用的时候再去拿去连接,无法生成连接,然后,由于maxWait默认值是-1(永久等待)。所以执行的时候导致超时。

具体的ISSUE地址:https://github.com/lettuce-io/lettuce-core/issues

当然以上只是推测,没有去验证,后面有空了,去验证下是不是上述的原因。

解决

把springBoot中lettuce-core的jarexclude掉。让SpringBoot使用jedis去加载它。

 

Spring Boot 集成 Redis 后,如果遇到中文字符乱码的问题,这通常是因为编码格式设置不一致导致的。解决这个问题需要关注以下几点: 1. **Redis 的配置**:确保 Redis 的配置文件中 (`redis.conf`) 或者客户端连接池中设置了正确的字符集(如 UTF-8),默认情况下,Redis 默认支持 ASCII 编码。 ```bash # redis.conf 中添加 config set string.default-string-coding=utf-8 ``` 2. **Spring Boot 配置**:在 Spring Boot 应用中,你需要配置 Jackson JSON 模板使用 UTF-8 编码,以及 RedisTemplate 的序列化器也应设置为支持 Unicode。 ```java @Configuration public class JacksonConfig { @Bean public MappingJackson2HttpMessageConverter jackson2HttpMessageConverter() { MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(); converter.setObjectMapper(new ObjectMapper().configure(SerializationFeature.INDENT_OUTPUT, true) .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) .setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"))); return converter; } } // 或者在 RedisTemplate 上设置序列化和反序列化 @Bean public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory connectionFactory) { StringRedisTemplate template = new StringRedisTemplate(); template.setKeySerializer(new StringRedisSerializer()); template.setValueSerializer(new GenericToStringSerializer<>(YourClass.class)); template.afterPropertiesSet(); return template; } ``` 3. **客户端操作**:在访问 Redis 时,确保你正确地将 Java 对象转换为字符串,并使用对应的序列化工具,如 `StringRedisTemplate.opsForValue()`。 4. **数据库查询结果**:如果你从 Redis 直接读取数据,记得处理返回值,比如使用 Redisson 这样的 Redis 客户端库,它会自动处理编码。 检查并调整以上配置应该可以帮助解决中文字符乱码问题。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值