首页 > 解决方案 > Spring Boot Redis 缓存创建许多新的 Redis 连接

问题描述

我正在使用带有 @Cacheable 注释的内置 Spring Boot 1 Redis 库来缓存 Redis 中的一些值。Redis 集群托管在 AWS 中,并且是非集群的,启用了 SSL 和密码。

我使用注释的一个例子是:

    @Cacheable(value = "example", key = "'example-'.concat(#id.toString())")
    public List<DTO> getById(Long id) {
        List<DBObject> dbObjectList = dbClient.getById(id);
        return dbObjectList.stream()
            .map(dbObject -> transformer.transformToDTO(dbObject))
            .collect(Collectors.toList());
    }

我正在使用 Lettuce 连接到集群,因为 Spring Boot 1 Jedis 和通过 SSL 连接存在问题。我的 Redis 配置是:

    @Bean
    public RedisConnectionFactory redisConnectionFactory() {
        LettuceConnectionFactory lettuceConnectionFactory = new LettuceConnectionFactory();
        lettuceConnectionFactory.setHostName(host);
        lettuceConnectionFactory.setPort(port);
        lettuceConnectionFactory.setPassword(password);
        lettuceConnectionFactory.setUseSsl(ssl);
        return lettuceConnectionFactory;
    }

    @Bean
    public static <T> RedisTemplate<String, T> redisTemplate(RedisConnectionFactory redisConnectionFactory,
                                                             ObjectMapper objectMapper) {
        GenericJackson2JsonRedisSerializer genericJackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer(objectMapper);
        RedisTemplate<String, T> template = new RedisTemplate<>();
        template.setConnectionFactory(redisConnectionFactory);
        template.setKeySerializer(new StringRedisSerializer());
        template.setValueSerializer(genericJackson2JsonRedisSerializer);
        template.setHashKeySerializer(new StringRedisSerializer());
        template.setHashValueSerializer(genericJackson2JsonRedisSerializer);
        return template;
    }

其中主机、端口、密码和 ssl 都通过 application.yml/environment 属性进行配置。

我的 Redis 缓存通过以下方式配置:

    @Bean
    public <T> RedisCacheManager redisCacheManager(RedisTemplate<String, T> redisTemplate) {
        final List<String> cacheNamesList = Arrays.asList(cacheName);
        final RedisCacheManager redisCacheManager = new RedisCacheManager(redisTemplate, cacheNamesList);
        final Map<String, Long> expiresMap = new HashMap<>();
        expiresMap.put(cacheName, cacheTTL);
        redisCacheManager.setExpires(expiresMap);
        return redisCacheManager;
    }

这一切都按预期工作,并且使用正确的 TTL 正确缓存了值。我遇到的问题是 AWS Redis 指标显示创建了很多新连接(根据 Cloudwatch 指标,一分钟内有超过 2000 个新连接)。

我假设生菜在线程之间共享连接,但似乎情况并非如此。我的生菜配置设置不正确吗?我想我可以通过升级到 Spring Boot 2 来解决这个问题,但这并不是一个简单的升级,因为它是一个相当大的应用程序,我希望我可以在 Spring Boot 1 中解决这个问题。

这些新连接不是问题吗?我知道 Redis 确实有连接限制,但看起来我的应用程序并没有接近限制。

AWS 指标

标签: javaspring-bootcachingredislettuce

解决方案


推荐阅读