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; } } }