我们有rest API应用程序。我们使用redis进行API响应缓存和内部方法缓存。如果redis连接,则它会使我们的API关闭。如果redis连接失败或任何异常,我们希望绕过redis缓存,而不是使我们的API关闭。有一个接口CacheErrorHandler,但它处理redis get set操作失败而不是redis连接问题。我们使用Spring 4.1.2。
我们有rest API应用程序。我们使用redis进行API响应缓存和内部方法缓存。如果redis连接,则它会使我们的API关闭。如果redis连接失败或任何异常,我们希望绕过redis缓存,而不是使我们的API关闭。有一个接口CacheErrorHandler,但它处理redis get set操作失败而不是redis连接问题。我们使用Spring 4.1.2。
9条答案
按热度按时间ct3nt3jp1#
让我们把这个问题简单地说一下。你的应用程序使用缓存(用Redis实现)。如果Redis连接过时/关闭或其他情况,那么你希望应用程序绕过缓存并(大概)直接进入底层数据存储(例如RDBMS)。应用程序服务逻辑可能看起来类似于...
Spring core的Caching Abstraction中确定Cache“miss”的所有问题是返回的值为null。因此,Spring Caching Infrastructure将继续调用实际的Service方法(即getCustomer)。请记住getCustomerRepo().load(customerId)调用的返回,您还需要处理Spring的Caching Infrastructure现在尝试缓存值的情况。
本着“保持简单”的精神,我们将不使用AOP,但您也应该能够使用AOP(您的选择)来实现这一点。
您所需要的只是一个扩展SDR CacheManager implementation的“自定义”RedisCacheManager,类似于...
因此,如果Redis不可用,也许你能做的最好的事情就是记录问题并继续让服务调用发生。显然,这会影响性能,但至少会提高对问题存在的意识。显然,这可以绑定到一个更强大的通知系统中,但这只是一个粗略的例子。重要的是,您的服务仍然可用,而应用服务所依赖的其他服务(例如Redis)可能已经失败。
在该实现中(相对于我之前的解释)我选择委托给底层的,实际的RedisCache实现,让异常发生,然后完全知道Redis存在问题,这样你就可以适当地处理异常。但是,如果你在检查时确定异常与连接问题有关,你可以返回“null”来让Spring Caching Infrastructure继续,就像它是一个Cache“miss”一样(即在本例中,坏的Redis连接== Cache miss)。
我知道这样的东西应该可以帮助您解决问题,因为我为GemFire和Pivotal的一个客户构建了一个类似的“自定义”CacheManager实现原型。该高速缓存“未命中”必须由应用程序域对象的“过时版本”触发,其中生产具有通过Spring的Caching Abstraction连接到GemFire的较新和较旧应用程序客户端的混合。例如,应用程序域对象字段在应用程序的较新版本中会发生更改。
无论如何,希望这对你有帮助或给你更多的想法。
干杯!
qcuzuvrc2#
所以,我今天正在挖掘核心Spring Framework Caching Abstraction源代码,解决另一个问题,似乎如果CacheErrorHandler正确实现,那么可能有问题的Redis Connection仍然会导致所需的行为,例如缓存“未命中”(由返回null值触发)。
有关更多详细信息,请参见AbstractCacheInvoker源代码。
cache.get(key)
应该会由于Redis连接错误而导致异常,因此会调用Exception处理程序...如果CacheErrorHandler正确处理了Cache“get”错误(并且没有重新抛出/an Exception),则将返回一个空值,指示缓存“miss”。
nukf8bse3#
谢谢@John Blum。我在
Spring Boot
中的解决方案如下。k3fezbri4#
实际上,我的回应是针对@Vivek Aditya先生的-我面临着同样的问题:新的spring-data-redis API,而不是每个RedisTemplate构造RedisCacheManager。唯一的选择-基于@John Blum的建议-是使用方面。下面是我的代码。
适用于所有合理的场景:
编辑:代码更像是一个poc --只用于“get”,我不喜欢在每次缓存命中时都重新示例化FailoverRedisCache--应该有一个Map。
unftdfkk5#
在使用Sping Boot 2.3.9.release和Redis时,上述方法都不适用。我们最终创建并注册了自己的自定义CacheErrorHandler,名为CustomCacheErrorHandler,以覆盖Spring Framework提供的默认SimpleCacheErrorHandler。这将完美地工作。
ljsrvy3e6#
我也遇到了同样的问题,但是,不幸的是,上面的解决方案都不适合我。我检查了这个问题,发现如果没有连接到Redis,执行的命令永远不会超时。所以我开始研究lettuce库来解决这个问题。我通过在没有连接的情况下拒绝命令来解决这个问题:
6ss1mwsb7#
所有核心 Spring FrameworkCache抽象注解(例如@Cacheable)沿着核心SF支持的JSR-107 JCache注解都委托给底层的CacheManager,对于Redis,就是RedisCacheManager。
您将在Spring XML配置元数据中配置RedisCacheManager,类似于此处。
一种方法是为(Redis)CacheManager编写一个AOP代理,它使用RedisConnection(间接来自RedisTemplate)来确定每个(Redis)CacheManager操作的连接状态。
如果连接失败或关闭,对于标准缓存操作,(Redis)CacheManager可以返回一个RedisCache的示例,用于getCache(String name),该示例总是返回null(表示条目上的缓存未命中),从而传递到底层数据存储。
也许有更好的方法来处理这个问题,因为我不是一个Maven的所有事情Redis(或SDR),但这应该工作,也许给予你一些想法自己。
干杯。
pes8fvy98#
Spring提供了内置的实现,用于在该高速缓存提供者服务器(例如:Redis)不可达或访问该高速缓存时发生运行时异常,只需使用LoggingCacheErrorHandler将异常记录为警告即可。
默认情况下Spring auto configuresCacheErrorHandlerof typeSimpleCacheErrorHandler,它只是抛出异常。所以为了避免抛出异常-〉我们需要做的就是使用以下配置覆盖cacheErrorHandler:
这将确保该高速缓存失败异常不会再传播或使您的应用程序或API失败。同时,您将这些异常记录为警告,我们可以根据这些警告采取行动。
注意:我已经用 spring-boot 2.7.10 测试过了
sczxawaw9#
你可以使用
CacheErrorHandler
。但是你应该确保在Redis缓存配置中将RedisCacheManager transactionAware
设置为false
(确保事务在执行缓存部分时提前提交,并且错误被CacheErrorHandler
捕获,并且不要等到执行结束时才跳过CacheErrorHandler
部分)。将transactionAware
设置为false
的函数如下所示: