


How to solve the timeout exception when Springboot2.x integrates lettuce and connects to the redis cluster
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
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>
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
Click on spring-boot-starter-data-redis and find it inside Contains lettuce dependencies:
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 }
Print output——
测试打印驱动类型:org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory@74ee761e
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>
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 }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}) 3It 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 } 22Then 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>
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>
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!

Redisoutperformstraditionaldatabasesinspeedforread/writeoperationsduetoitsin-memorynature,whiletraditionaldatabasesexcelincomplexqueriesanddataintegrity.1)Redisisidealforreal-timeanalyticsandcaching,offeringphenomenalperformance.2)Traditionaldatabase

UseRedisinsteadofatraditionaldatabasewhenyourapplicationrequiresspeedandreal-timedataprocessing,suchasforcaching,sessionmanagement,orreal-timeanalytics.Redisexcelsin:1)Caching,reducingloadonprimarydatabases;2)Sessionmanagement,simplifyingdatahandling

Redis goes beyond SQL databases because of its high performance and flexibility. 1) Redis achieves extremely fast read and write speed through memory storage. 2) It supports a variety of data structures, such as lists and collections, suitable for complex data processing. 3) Single-threaded model simplifies development, but high concurrency may become a bottleneck.

Redis is superior to traditional databases in high concurrency and low latency scenarios, but is not suitable for complex queries and transaction processing. 1.Redis uses memory storage, fast read and write speed, suitable for high concurrency and low latency requirements. 2. Traditional databases are based on disk, support complex queries and transaction processing, and have strong data consistency and persistence. 3. Redis is suitable as a supplement or substitute for traditional databases, but it needs to be selected according to specific business needs.

Redisisahigh-performancein-memorydatastructurestorethatexcelsinspeedandversatility.1)Itsupportsvariousdatastructureslikestrings,lists,andsets.2)Redisisanin-memorydatabasewithpersistenceoptions,ensuringfastperformanceanddatasafety.3)Itoffersatomicoper

Redis is primarily a database, but it is more than just a database. 1. As a database, Redis supports persistence and is suitable for high-performance needs. 2. As a cache, Redis improves application response speed. 3. As a message broker, Redis supports publish-subscribe mode, suitable for real-time communication.

Redisisamultifacetedtoolthatservesasadatabase,server,andmore.Itfunctionsasanin-memorydatastructurestore,supportsvariousdatastructures,andcanbeusedasacache,messagebroker,sessionstorage,andfordistributedlocking.

Redisisanopen-source,in-memorydatastructurestoreusedasadatabase,cache,andmessagebroker,excellinginspeedandversatility.Itiswidelyusedforcaching,real-timeanalytics,sessionmanagement,andleaderboardsduetoitssupportforvariousdatastructuresandfastdataacces


Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

SublimeText3 Chinese version
Chinese version, very easy to use

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Linux new version
SublimeText3 Linux latest version

MantisBT
Mantis is an easy-to-deploy web-based defect tracking tool designed to aid in product defect tracking. It requires PHP, MySQL and a web server. Check out our demo and hosting services.

SAP NetWeaver Server Adapter for Eclipse
Integrate Eclipse with SAP NetWeaver application server.
