springboot2.x集成redis。redis節點故障,集群狀態ok的情況下,程序使用redisTemplate操作redis一直報錯:
Redis command timed out; nested exception is io.lettuce.core.RedisCommandTimeoutException: Command timed out after 1 minute(s)
解決方案:捕獲redisTemplate操作的異常,然后重新初始化redisTemplate的連接工廠connectionFactory
代碼如下:
RedisService.java
package com.harara; import com.harara.RedisConfig; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Primary; import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.ValueOperations; import org.springframework.stereotype.Component; import java.io.Serializable; /** * @author: harara * @date: 2020-9-07 18:23 * @description: * @version: 1.0 */ @Slf4j @Component public class RedisService { @Autowired private RedisTemplate redisTemplate; @Autowired private RedisConfig redisConfig; /** * 更新redisTemplate :處理集群宕機恢復后程序不恢復問題
* 重新初始化redisTemplate的連接工廠connectionFactory */ private RedisTemplate refreshRedisTemplate(){ LettuceConnectionFactory connectionFactory = redisConfig.connectionFactory(); connectionFactory.afterPropertiesSet(); redisTemplate.setConnectionFactory(connectionFactory); return redisTemplate; } /** * @param key * @return */ public Object get(final String key){ ValueOperations<Serializable, Object> operations = null; try { operations= redisTemplate.opsForValue(); return operations.get(key); }catch (Exception e){ log.error("redis操作string get出現異常:{}",e.getMessage()); operations = refreshRedisTemplate().opsForValue(); return operations.get(key); } } }
RedisConfig.java
package com.harara; import cn.hutool.core.util.StrUtil; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Configuration; import org.springframework.core.annotation.Order; import org.springframework.core.env.MapPropertySource; import org.springframework.data.redis.connection.RedisClusterConfiguration; import org.springframework.data.redis.connection.RedisStandaloneConfiguration; import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; import java.util.HashMap; import java.util.Map; /** * redis 配置類 * @author harara * @date 2020/9/7 11:34 * */ @Configuration @Order(value = 1) public class RedisConfig { //redis連接的database @Value("${spring.redis.database:0}") private int database; //集群節點配置 @Value("${spring.redis.cluster.nodes:#{null}}") private String nodes; //集群最大連接轉移數 @Value("${spring.redis.cluster.max-redirects:3}") private int maxRedirects; //單節點情況下redis的ip @Value("${spring.redis.host:#{null}}") private String host; //單節點情況下redis的端口 @Value("${spring.redis.port:#{null}}") private Integer port; //redis的連接密碼 @Value("${spring.redis.password:#{null}}") private String password; /** * 創建連接工廠LettuceConnectionFactory * @return */ public LettuceConnectionFactory connectionFactory() { Map<String, Object> source = new HashMap<String, Object>(); RedisClusterConfiguration redisClusterConfiguration; RedisStandaloneConfiguration redisStandaloneConfiguration; //集群模式 if(nodes !=null){ source.put("spring.redis.cluster.nodes", nodes); source.put("spring.redis.cluster.max-redirects", maxRedirects); redisClusterConfiguration = new RedisClusterConfiguration(new MapPropertySource("RedisClusterConfiguration", source)); if(!StrUtil.isEmpty(password)){ redisClusterConfiguration.setPassword(password); } //創建連接工廠 LettuceConnectionFactory lettuceConnectionFactory = new LettuceConnectionFactory(redisClusterConfiguration); return lettuceConnectionFactory; }else{ //單機模式 redisStandaloneConfiguration = new RedisStandaloneConfiguration(host,port); redisStandaloneConfiguration.setDatabase(database); if(!StrUtil.isEmpty(password)){ redisStandaloneConfiguration.setPassword(password); } //創建連接工廠 LettuceConnectionFactory lettuceConnectionFactory = new LettuceConnectionFactory(redisStandaloneConfiguration); return lettuceConnectionFactory; } } }