Spring Cache with Redis - 如果与 Redis 的连接失败,如何优雅地处理甚至跳过缓存

Posted

技术标签:

【中文标题】Spring Cache with Redis - 如果与 Redis 的连接失败,如何优雅地处理甚至跳过缓存【英文标题】:Spring Cache with Redis - How to gracefully handle or even skip Caching in case of Connection Failure to Redis 【发布时间】:2015-02-26 18:14:39 【问题描述】:

我已在我的 Spring 应用程序中启用缓存,并使用 Redis 来实现此目的。 但是,每当发生连接故障时,应用程序就会停止工作,而我认为它最好 跳过缓存并继续正常的执行流程。

那么,有没有人知道如何在 Spring 中优雅地做到这一点?

这是我得到的例外。

Caused by: org.springframework.data.redis.RedisConnectionFailureException: Cannot get Jedis connection; nested exception is redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool

【问题讨论】:

【参考方案1】:

您可以按照 Stephane Nicoll 的建议使用 CacheErrorHandler。但你应该确保 RedisCacheManager transactionAwarefalse 在你的 Redis 缓存配置中(以确保在执行缓存部分时尽早提交事务并且错误被 CacheErrorHandler 捕获,不要等到跳过 @987654325 的执行结束@ 部分)。将transactionAware 设置为false 的函数如下所示:

    @Bean
    public RedisCacheManager redisCacheManager(LettuceConnectionFactory lettuceConnectionFactory) 
        JdkSerializationRedisSerializer redisSerializer = new JdkSerializationRedisSerializer(getClass().getClassLoader());

        RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
                .entryTtl(Duration.ofHours(redisDataTTL))
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer));

        redisCacheConfiguration.usePrefix();

        RedisCacheManager redisCacheManager = RedisCacheManager.RedisCacheManagerBuilder.fromConnectionFactory(lettuceConnectionFactory)
                .cacheDefaults(redisCacheConfiguration)
                .build();

        redisCacheManager.setTransactionAware(false);
        return redisCacheManager;
    

【讨论】:

它对我有用,但我害怕将缓存排除在事务之外【参考方案2】:

Stephane Nicoll 建议的 CacheErrorHandler 很有用。但是当它无法创建与redis的连接时,它并没有帮助。

像@Cacheable Stills 这样的缓存方法失败并出现 RedisConnectionFailureException。

【讨论】:

对我来说也一样。你找到解决办法了吗?【参考方案3】:

与 Stephane 提到的类似,我通过使用 try catch 块中的错误来完成。添加一个回退机制,如果 Redis 未启动或数据不存在,则我从 DB 中获取数据。(稍后如果我找到一个,然后我在 Redis 中添加相同的数据,如果它是为了保持一致性。 )

【讨论】:

【参考方案4】:

从 Spring Framework 4.1 开始,您可以实现一个 CacheErrorHandler 来处理此类异常。详情请参考to the javadoc。

您可以通过让您的@Configuration 类扩展CachingConfigurerSupport 来注册它(请参阅errorHandler())。

【讨论】:

非常感谢您的建议。我的@Configuration 类已经扩展了 SpringBootServletInitializer,因此,我尝试直接从我的@Configuration 类中实现 CacheErrorHandler。但是,它似乎无法处理 RedisConnectionFailureException 之类的任何问题。 您在哪里看到了对SpringBootServletInitializer 的引用?我写了CachingConfigurerSupport - 为此,您需要 Spring Boot 1.2 (Spring 4.1)。 CacheErrorHandler 仅在缓存操作期间使用。 Redis 连接失败可能发生在更高层? 呃?上级是什么意思? 我想他大概的意思是当连接失败时,可能不会触发CacheErrorHandler

以上是关于Spring Cache with Redis - 如果与 Redis 的连接失败,如何优雅地处理甚至跳过缓存的主要内容,如果未能解决你的问题,请参考以下文章

Spring Boot 整合 Spring Cache + Redis

spring-boot Cache redis 类型转换错误

Spring Boot之集成Redis:Spring Cache + Redis

Spring Boot集成Spring Cache 和 Redis

04-使用Spring Cache+Redis来完成对字典数据缓存

SpringBoot 结合 Spring Cache 操作 Redis 实现数据缓存