关于SpringBoot整合redis使用Lettuce客户端超时问题

网友投稿 1480 2022-12-21

关于SpringBoot整合redis使用Lettuce客户端超时问题

关于SpringBoot整合redis使用Lettuce客户端超时问题

参考的博客

问题起因

做毕设的时候,使用到Lettuce连接redis,一段时间后不操作,再去操作redis,会报连接超时错误,在其重连后又可使用。

原因是:Lettuce 自适应拓扑刷新(Adaptive updates)与定时拓扑刷新(Periodic updates) 是默认关闭的导致问题的出现

解决的方案

1、重写连接工厂实例,更改其LettuceClientConfiguration 为开启拓扑更新

@Configuration

public class RedisConfig {

@Autowired

private RedisProperties redisProperties;

//这是固定的模板

//自己定义了一个RedisTemplate

@Bean

@SuppressWarnings("all")

public RedisTemplate redisTemplataretAee(@Qualifier("lettuceConnectionFactoryUvPv") RedisConnectionFactory factory) {

RedisTemplate template = new RedisTemplate<>();

template.setConnectionFactory(factory);

//json序列配置

Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);

ObjectMapper om = new ObjectMapper();

om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);

om.activateDefaultTyping(om.getPolymorphicTypeValidator());

om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);

//解决序列化问题

om.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

jackson2JsonRedisSerializer.setObjectMapper(om);

//String的序列化

StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();

//key采用String的序列化方式

template.setKeySerializer(stringRedisSerializer);

//hash的key也采用String的序列化方式

template.setHashKeySerializer(stringRedisSerializer);

//value序列化方式采用jackson

template.setValueSerializer(jackson2JsonRedisSerializer);

//hash的value序列化方式采用jackson

template.setHashValueSerializer(jackson2JsonRedisSerializer);

template.afterPropertiesSet();

return template;

}

/**

* 为RedisTemplate配置Redis连接工厂实现

* LettuceConnectionFactory实现了RedisConnectionFactory接口

* UVPV用Redis

*

* @return 返回LettuceConnectionFactory

*/

@Bean(destroyMethod = "destroy")

//这里要注意的是,在构建LettuceConnectionFactory 时,如果不使用内置的destroyMethod,可能会导致Redis连接早于其它Bean被销毁

public LettuceConnectionFactory lettuceConnectionFactoryUvPv() throws Exception {

List clusterNodes = redisProperties.getCluster().getNodes();

Set nodes = new HashSet<>();

clusterNodes.forEach(address -> nodes.add(new RedisNode(address.split(":")[0].trim(), Integer.parseInt(address.split(":")[1]))));

RedisClusterConfiguration clusterConfiguration = new RedisClusterConfiguration();

clusterConfiguration.setClusterNodes(nodes);

clusterConfiguration.setPassword(RedisPassword.of(redisProperties.getPassword()));

clusterConfiguration.setMaxRedirects(redisProperties.getCluster().getMaxRedirects());

RedisStandaloneConfiguration redisStandaloneConfiguration=new RedisStandaloneConfiguration();

redisStandaloneConfiguration.setHostName(redisProperties.getHost());

redisStandaloneConfiguration.setPassword(redisProperties.getPassword());

redisStandaloneConfiguration.setDatabase(redisProperties.getDatabase());

redisStandaloneConfiguration.setPort(redisProperties.getPort());

GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();

poolConfig.setMaxIdle(redisProperties.getLettuce().getPool().getMaxIdle());

poolConfig.setMinIdle(redisProperties.getLettuce().getPool().getMinIdle());

poolConfig.setMaxTotal(redisProperties.getLettuce().getPool().getMaxActive());

return new LettuceConnectionFactory(redisStandaloneConfiguration, getLettuceClientConfiguration(poolConfig));

}

/**

* 配置LettuceClientConfiguration 包括线程池配置和安全项配置

*

* @param genericObjectPoolConfig common-pool2线程池

* @return lettuceClientConfiguration

*/

private LettuceClientConfiguration getLettuceClientConfiguration(GenericObjectPoolConfig genericObjectPoolConfig) {

/*

ClusterTopologyRefreshOptions配置用于开启自适应刷新和定时刷新。如自适应刷新不开启,Redis集群变更时将会导致连接异常!

*/

ClusterTopologyRefreshOptions topologyRefreshOptions = ClusterTopologyRefreshOptions.builder()

//开启自适应刷新

//.enableAdaptiveRefreshTrigger(ClusterTopologyRefreshOptions.RefreshTrigger.MOVED_REDIRECT, ClusterTopologyRefreshOptions.RefreshTrigger.PERSISTENT_RECONNECTS)

//开启所有自适应刷新,MOVED,ASK,PERSISTENT都会触发

.enableAllAdaptiveRefreshTriggers()

// 自适应刷新超时时间(默认30秒)

.adaptiveRefreshTriggersTimeout(Duration.ofSeconds(25)) //默认关闭开启后时间为30秒

// 开周期刷新

.enablePeriodicRefresh(Duration.ofSeconds(20)) // 默认关闭开启后时间为60秒 ClusterTopologyRefreshOptions.DEFAULT_REFRESH_PERIOD 60 .enablePeriodicRefresh(Duration.ofSeconds(2)) = .enablePeriodicRefresh().refreshPeriod(Duration.ofSeconds(2))

.build();

return LettucePoolingClientConfiguration.builder()

.poolConfig(genericObjectPoolConfig)

.clientOptions(ClusterClientOptions.builder()-ologyRefreshOptions(topologyRefreshOptions).build())

//将appID传入连接,方便Redis监控中查看

//.clientName(appName + "_lettuce")

.build();

}

}

2、SpringBoot2.3.x后,可使用配置文件中开启lettuce的拓扑刷新

lettuce:

pool:

max-active: 20

max-wait: -1ms

max-idle: 10

min-idle: 2

cluster:

refresh:

adaptive: true

#20秒自动刷新一次

period: 20

3、更改连接redis的连接方式,使用jedis连接

org.springframework.boot

spring-boot-starter-data-redis

io.lettuce

lettuce-core

redis.clients

jedis

spring:

redis:

jedis:

pool:

max-active: ${redis.config.maxTotal:1024}

max-idle: ${redis.config.maxIdle:50}

min-idle: ${redis.config.minIdle:1}

max-wait: ${redis.config.maxWaitMillis:5000}

#lettuce:

#pool:

#max-active: ${redis.config.maxTotal:1024}

#max-idle: ${redis.config.maxIdle:50}

#min-idle: ${redis.config.minIdle:1}

#max-wait: ${redis.config.maxWaitMillis:5000}

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:咸阳一体化政务服务平台(咸阳市政府网官网首页)
下一篇:软件制作app开发(APP制作开发)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~