SpringBoot整合redis, RedisTemplate默认使用Lettuce客户端超时问题

SpringBoot整合redis, RedisTemplate默认使用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<String, Object> redisTemplate(@Qualifier("lettuceConnectionFactoryUvPv") RedisConnectionFactory factory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(factory);
 
        //Json序列化配置
        Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<Object>(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<String> clusterNodes = redisProperties.getCluster().getNodes();
//        Set<RedisNode> 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());
 
        //我使用的是单机redis,集群使用上面注释的代码
        Set<RedisNode> nodes = new HashSet<>();
        nodes.add(new RedisNode(redisProperties.getHost(), redisProperties.getPort()));
 
 
        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().topologyRefreshOptions(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

方法二:

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

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>io.lettuce</groupId>
                    <artifactId>lettuce-core</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
         
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
        </dependency>

配置文件

spring:
  redis:
    password: xxx
    host: 172.16.0.x
    port: 6579
    timeout: 5000
    jedis:
      pool:
              #最大连接数据库连接数,设 0 为没有限制
        max-active: 8
              #最大等待连接中的数量,设 0 为没有限制
        max-idle: 8
              #最大建立连接等待时间。如果超过此时间将接到异常。设为-1表示无限制。
        max-wait: -1ms
              #最小等待连接中的数量,设 0 为没有限制
        min-idle: 0
    #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}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: Spring Boot可以通过Lettuce整合RedisLettuce是一个高性能的Redis客户端,支持异步、响应式和线程安全的操作。在Spring Boot中,我们可以通过添加Lettuce的依赖来使用它。然后,我们需要在application.properties文件中配置Redis的连接信息,包括主机名、端口号、密码等。最后,我们可以通过注入LettuceConnectionFactory来获取Redis连接,然后使用RedisTemplate或者ReactiveRedisTemplate来进行Redis操作。 ### 回答2: Redis是一种高效的NoSQL数据库,通过使用SpringBoot框架与Redislettuce进行集成,我们可以轻松地在应用程序中使用Redis实现缓存,定时任务和消息队列等功能。 1. 添加Redislettuce依赖 我们需要在项目的pom.xml文件中添加redislettuce的依赖项,以便能够在应用程序中使用redislettuce客户端。 ``` <dependency> <groupId>io.lettuce</groupId> <artifactId>lettuce-core</artifactId> <version>x.x.x</version> </dependency> ``` 注:x为当前最新版本号 2. 配置redislettuce客户端 我们需要在应用程序中创建一个RedisConnectionFactory实例,通过该实例连接Redis数据库。我们可以使用LettuceConnectionFactory类来创建RedisConnectionFactory实例。 在我们的Spring Boot应用程序中,我们可以通过application.yml或application.properties文件配置Redis数据库的相关信息。 ``` spring.redis.host=localhost spring.redis.port=6379 spring.redis.password= ``` 我们可以通过配置类将redislettuce客户端注册到Spring容器中,以便在应用程序中使用。 ``` @Configuration @EnableCaching public class RedisLettuceConfig { @Autowired private Environment env; @Bean public RedisConnectionFactory redisConnectionFactory() { LettuceClientConfiguration clientConfig = LettuceClientConfiguration.builder() .useSsl().and() .commandTimeout(Duration.ofSeconds(2)) .shutdownTimeout(Duration.ZERO) .build(); RedisStandaloneConfiguration serverConfig = new RedisStandaloneConfiguration( env.getProperty("spring.redis.host"), Integer.parseInt(env.getProperty("spring.redis.port"))); return new LettuceConnectionFactory(serverConfig, clientConfig); } @Bean public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) { RedisTemplate<String, Object> template = new RedisTemplate<>(); template.setConnectionFactory(redisConnectionFactory); template.setKeySerializer(new StringRedisSerializer()); template.setValueSerializer(new JdkSerializationRedisSerializer()); return template; } } ``` 3. 使用redislettuce 我们可以在我们的Java代码中使用Spring缓存抽象缓存结果,Spring会根据其缓存配置自动缓存和加载数据。我们可以使用Spring的CacheAbstraction为存储在Redis中的数据创建缓存注解。 ``` @Cacheable(value="Category", key="‘category_cache_’+#root.args[0]") public Category getCategoryById(Long id) { // fetch category by id // if not found, return null return category; } @CachePut(value="Category", key="‘category_cache’+#root.args[0].id") public Category updateCategory(Category category) { // update category // return updated category } @CacheEvict(value="Category", key="‘category_cache’+#root.args[0]") public void deleteCategoryById(Long id) { // delete category by id } ``` 我们可以通过以下方式操作redis: ``` @Autowired private RedisTemplate<String,Object> redisTemplate; public void add(String key, Object value) { redisTemplate.opsForValue().set(key, value); } public Object get(String key) { return redisTemplate.opsForValue().get(key); } public void delete(String key) { redisTemplate.delete(key); } ``` 总结 使用Spring Boot框架与Redislettuce进行集成,我们可以轻松地在应用程序中使用Redis实现缓存,定时任务和消息队列等功能。步骤如下: 1. 添加Redislettuce依赖 2. 配置redislettuce客户端 3. 使用redislettuce 该应用程序允许简单的操作redis数据库。无论是在单个节点还是在集群中,redis集成都将非常实用。使用redislettuce的标准连接池大小和异步API支持,可以轻松地处理高负载、高并发的场景。 ### 回答3: Spring Boot是一个开源框架,用于构建可扩展和可配置的Java应用程序。它提供了一组流行的功能,在开发人员中广泛使用Redis是一种基于内存的高性能键值数据存储系统,可以用于缓存和持久化数据。 Lettuce是一个高级的Redis客户端库,支持异步、可扩展、非阻塞、事件驱动模型。它还支持集群、TLS、Redis Sentinel等强大功能。在Spring Boot中,可以通过使用Lettuce来集成Redis。 下面是使用Spring Boot整合Redis Lettuce的步骤: 第一步是添加依赖项。在Maven项目中,我们需要添加以下依赖项: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <dependency> <groupId>io.lettuce</groupId> <artifactId>lettuce-core</artifactId> <version>X.Y.Z</version> </dependency> ``` 请注意,`X.Y.Z`应替换为所需的Lettuce版本。 第二步是配置Redis连接。我们可以使用application.properties或application.yml文件来配置Redis连接。下面是一个简单的例子: ```yaml spring.redis.host=localhost spring.redis.port=6379 ``` 这里我们指定Redis服务器的主机和端口。 第三步是在应用程序中使用Redis。我们可以使用Spring Boot提供的`RedisTemplate`类来访问Redis。在以下示例中,我们向Redis中设置字符串,并在稍后检索它: ```java @Autowired private RedisTemplate<String, String> redisTemplate; public void setKey(String key, String value) { redisTemplate.opsForValue().set(key, value); } public String getKey(String key) { return redisTemplate.opsForValue().get(key); } ``` 请注意,`RedisTemplate`类使用Spring Boot自动配置中指定的Redis连接。我们可以通过调用`opsForValue()`方法来访问Redis字符串。 最后,我们需要确保Redis服务器已启动,并在应用程序启动时连接。 总之,通过上述步骤,我们可以轻松地在Spring Boot中集成Redis Lettuce,并使用Spring Boot提供的RedisTemplate来访问Redis。这些步骤可以提高应用程序的性能和可伸缩性,以满足不同业务场景的需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值