Home > Database > Redis > body text

How to solve the timeout exception when Springboot2.x integrates lettuce and connects to the redis cluster

PHPz
Release: 2023-05-27 19:43:05
forward
1906 people have browsed it

Background: Recently, I was doing a stress test on the Springboot system developed by Yixin. I found that when I first started the stress test, I could access data from the redis cluster normally. However, after a few minutes of pause, and then I continued to use jmeter to perform the stress test, I found that Redis started to suddenly and crazyly burst out abnormal prompts: Command timed out after 6 second(s)...

  1 Caused by: io.lettuce.core.RedisCommandTimeoutException: Command timed out after 6 second(s)  2     at io.lettuce.core.ExceptionFactory.createTimeoutException(ExceptionFactory.java:51)  3     at io.lettuce.core.LettuceFutures.awaitOrCancel(LettuceFutures.java:114)  4     at io.lettuce.core.cluster.ClusterFutureSyncInvocationHandler.handleInvocation(ClusterFutureSyncInvocationHandler.java:123)  5     at io.lettuce.core.internal.AbstractInvocationHandler.invoke(AbstractInvocationHandler.java:80)  6     at com.sun.proxy.$Proxy134.mget(Unknown Source)  7     at org.springframework.data.redis.connection.lettuce.LettuceStringCommands.mGet(LettuceStringCommands.java:119)  8     ... 15 common frames omitted
Copy after login

I hurriedly checked the redis cluster and found that all nodes in the cluster were normal, and the CPU and memory usage were It’s less than 20%. Looking at all this, I suddenly fell into a long meditation. What is the problem? After searching on Baidu, I found that many people have experienced similar situations. Some people said that the timeout setting should be changed. A bigger one will do the trick. I followed this solution and set the timeout value to a larger value, but the timeout problem was still not solved.

Among them, the dependency package for springboot to operate redis is——

  1 <dependency>  2     <groupId>org.springframework.boot</groupId>  3     <artifactId>spring-boot-starter-data-redis</artifactId>  4 </dependency>
Copy after login

Cluster configuration——

  1 redis:  2   timeout: 6000ms  3   cluster:  4     nodes:  5       - xxx.xxx.x.xxx:6379  6       - xxx.xxx.x.xxx:6379  7       - xxx.xxx.x.xxx:6379  8   jedis:  9     pool: 10       max-active: 1000 11       max-idle: 10 12       min-idle: 5 13       max-wait: -1
Copy after login

Click on spring-boot-starter-data-redis and find it inside Contains lettuce dependencies:

How to solve the timeout exception when Springboot2.x integrates lettuce and connects to the redis cluster

springboot1.x uses jedis by default, and springboot2.x uses lettuce by default. We can simply verify that in the redis driver loading configuration class, output the RedisConnectionFactory information:

  1 @Configuration  2 @AutoConfigureAfter(RedisAutoConfiguration.class)  3 public class Configuration {  4     @Bean  5     public StringRedisTemplate redisTemplate(RedisConnectionFactory factory) {  6         log.info("测试打印驱动类型:"+factory);  7 }
Copy after login

Print output——

测试打印驱动类型:org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory@74ee761e
Copy after login

It can be seen that the lettuce driver connection is used here , therefore, when it is replaced with the jedis driver connection that was used frequently before, the problem of Command timed out after 6 second(s) no longer occurs.

  1 <dependency>  2     <groupId>org.springframework.boot</groupId>  3     <artifactId>spring-boot-starter-data-redis</artifactId>  4     <exclusions>  5         <exclusion>  6             <groupId>io.lettuce</groupId>  7             <artifactId>lettuce-core</artifactId>  8         </exclusion>  9     </exclusions> 10 </dependency> 11 <dependency> 12     <groupId>redis.clients</groupId> 13     <artifactId>jedis</artifactId> 14 </dependency>
Copy after login

Then the question is, how does Springboot2.x use lettuce by default? We need to study some of the code inside. We can enter the redis part of the Springboot2. ##

  1 @Configuration(  2     proxyBeanMethods = false  3 )  4 @ConditionalOnClass({RedisOperations.class})  5 @EnableConfigurationProperties({RedisProperties.class})  6 @Import({LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class})  7 public class RedisAutoConfiguration {  8     public RedisAutoConfiguration() {  9    } 10    ......省略 11 }
Copy after login

This means that when using the spring-boot-starter-data-redis dependency, both lettuce and jedis drivers can be automatically imported. Logically speaking, there will not be two drivers at the same time, which does not make much sense. , therefore, the order here is very important. Why do you say this?

Enter LettuceConnectionConfiguration.class and JedisConnectionConfiguration.class respectively, each showing the core code that this article needs to involve:

  1   2 @Import({LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class})  3
Copy after login

It can be seen that LettuceConnectionConfiguration.class and JedisConnectionConfiguration.class have the same Annotate @ConditionalOnMissingBean({RedisConnectionFactory.class}), which means that if the RedisConnectionFactory bean has been registered in the container, then other beans similar to it will no longer be loaded and registered. To put it simply, for LettuceConnectionConfiguration and JedisConnectionConfiguration respectively With the @ConditionalOnMissingBean({RedisConnectionFactory.class}) annotation, only one of the two can be loaded and registered into the container, and the other one will not be loaded and registered.

So, the question is, who will be registered first?

This goes back to the sentence mentioned above, the order in @Import({LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class}) is very important. LettuceConnectionConfiguration is in front, which means that LettuceConnectionConfiguration will be register.

It can be seen that Springboot uses lettuce to connect to redis by default.

When we introduce the spring-boot-starter-data-redis dependency package, it is actually equivalent to introducing the lettuce package. At this time, the lettuce driver will be used. If you do not want to use the default lettuce driver, directly use lettuce Just exclude dependencies.

  1 //LettuceConnectionConfiguration  2 @ConditionalOnClass({RedisClient.class})  3 class LettuceConnectionConfiguration extends RedisConnectionConfiguration {  4    ......省略  5     @Bean  6     @ConditionalOnMissingBean({RedisConnectionFactory.class})  7     LettuceConnectionFactory redisConnectionFactory(ObjectProvider<LettuceClientConfigurationBuilderCustomizer> builderCustomizers, ClientResources clientResources) throws UnknownHostException {  8         LettuceClientConfiguration clientConfig = this.getLettuceClientConfiguration(builderCustomizers, clientResources, this.getProperties().getLettuce().getPool());  9         return this.createLettuceConnectionFactory(clientConfig); 10    } 11 } 12 //JedisConnectionConfiguration 13 @ConditionalOnClass({GenericObjectPool.class, JedisConnection.class, Jedis.class}) 14 class JedisConnectionConfiguration extends RedisConnectionConfiguration { 15    ......省略 16     @Bean 17     @ConditionalOnMissingBean({RedisConnectionFactory.class}) 18     JedisConnectionFactory redisConnectionFactory(ObjectProvider<JedisClientConfigurationBuilderCustomizer> builderCustomizers) throws UnknownHostException { 19         return this.createJedisConnectionFactory(builderCustomizers); 20    } 21 } 22
Copy after login

Then introduce the jedis dependency——

  1 <dependency>  2     <groupId>org.springframework.boot</groupId>  3     <artifactId>spring-boot-starter-data-redis</artifactId>  4     <exclusions>  5         <exclusion>  6             <groupId>io.lettuce</groupId>  7             <artifactId>lettuce-core</artifactId>  8         </exclusion>  9     </exclusions> 10 </dependency>
Copy after login

In this way, when performing the import annotation of RedisAutoConfiguration, because the lettuce dependency is not found, this annotation @Import({LettuceConnectionConfiguration.class , the JedisConnectionConfiguration in the second position of JedisConnectionConfiguration.class}) is now valid and can be registered to the container as the driver for springboot to operate redis.

What is the difference between lettuce and jedis?

lettuce: The bottom layer is implemented in netty, thread-safe, and has only one instance by default.

jedis: Can be directly connected to the redis server and used with the connection pool to increase physical connections.

Find the error method according to the exception prompt, lettuceConverters.toBoolean(this.getConnection().zadd(key, score, value)) in the following code——

  1 <dependency>  2     <groupId>redis.clients</groupId>  3     <artifactId>jedis</artifactId>  4 </dependency>
Copy after login

LettuceConverters.toBoolean() converts long to Boolean. Under normal circumstances, this.getConnection().zadd(key, score, value) returns 1 if the addition is successful, so LettuceConverters.toBoolean(1) gets is true, otherwise, if the new addition fails, 0 is returned, that is, LettuceConverters.toBoolean(0). There is also a third case, that is, an exception occurs in this.getConnection().zadd(key, score, value) method. What? What happens if an exception occurs?

It should be when the connection connection fails.

The above is the detailed content of How to solve the timeout exception when Springboot2.x integrates lettuce and connects to the redis cluster. For more information, please follow other related articles on the PHP Chinese website!

Related labels:
source:yisu.com
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
About us Disclaimer Sitemap
php.cn:Public welfare online PHP training,Help PHP learners grow quickly!