Java 如果缓存服务器出现故障,是否可以使应用程序忽略缓存?
我有一个具有以下属性的spring启动应用程序:Java 如果缓存服务器出现故障,是否可以使应用程序忽略缓存?,java,spring-boot,spring-data-redis,spring-cache,Java,Spring Boot,Spring Data Redis,Spring Cache,我有一个具有以下属性的spring启动应用程序: spring.cache.type: redis spring.redis.host: <hostname> spring.redis.port: <hostport> 我想避免这种情况……我只需要一种方法告诉spring“缓存崩溃了,但没关系:假装你根本没有缓存”@Phate-绝对!我刚刚回答了一个(可能的)问题,使用ApacheGeode或Pivotal GemFire作为Spring启动应用程序中的缓存提供程序,并
spring.cache.type: redis
spring.redis.host: <hostname>
spring.redis.port: <hostport>
我想避免这种情况……我只需要一种方法告诉spring“缓存崩溃了,但没关系:假装你根本没有缓存”@Phate-绝对!我刚刚回答了一个(可能的)问题,使用ApacheGeode或Pivotal GemFire作为Spring启动应用程序中的缓存提供程序,并使用Spring的缓存抽象 在那篇文章中,我没有完全禁用缓存,而是将GemFire/Geode切换为仅在本地模式下运行(GemFire/Geode的一种可能配置)。但是,如果需要,也可以应用相同的技术完全禁用缓存 本质上,在Spring引导和Spring开始评估应用程序的配置之前,您需要一个预处理步骤 在我的示例中,我实现了一个检查集群(即服务器)可用性的方法。然后,我将
条件
添加到我的@配置
类中
在springboot的情况下,springboot应用于Redis(作为存储和缓存提供程序),当它有效地(以及)应用程序的类路径上的Redis和springdataredis时。因此,从本质上讲,只有当“条件”为true时,才启用Redis作为缓存提供程序,主要是
RedisConnectionFactory
bean由您的应用程序配置决定,由您负责
那么,这会是什么样子
与我的Apache Geode和GemFire一样,您可以为Redis实现类似的条件,例如:
static RedisAvailableCondition implements Condition {
@Override
public boolean matches(ConditionContext conditionContext,
AnnotatedTypeMetadata annotatedTypeMetadata) {
// Check the available of the Redis server, such as by opening a Socket
// connection to the server node.
// NOTE: There might be other, more reliable/robust means of checking
// the availability of a Redis server in the Redis community.
Socket redisServer;
try {
Environment environment = conditionContext.getEnvironment();
String host = environment.getProperty("spring.redis.host");
Integer port = environment.getProperty("spring.redis.port", Integer.class);
SocketAddress redisServerAddress = new InetSocketAddress(host, port);
redisServer = new Socket();
redisServer.connect(redisServerAddress);
return true;
}
catch (Throwable ignore) {
System.setProperty("spring.cache.type", "none");
return false;
}
finally {
// TODO: You need to implement this method yourself.
safeCloseSocket(redisServer);
}
}
}
此外,我还将spring.cache.type
设置为NONE
,以确保在Redis不可用的情况下,缓存被呈现为无操作<代码>无将更详细地解释
当然,您也可以使用备用缓存选项,使用其他一些缓存提供程序(例如简单的ConcurrentHashMap
,但我将此作为练习留给您)。向前
然后,在Spring Boot应用程序配置类中,您已经定义了RedisConnectionFactory
bean(正如Spring Boot的自动配置所期望的那样),您可以使用Spring的@conditional
注释添加此自定义条件,如下所示:
@Confgiuration
@Conditional(RedisAvailableCondition.class);
class MyRedisConfiguration {
@Bean
RedisConnectionFactory redisConnectionFactory() {
// Construct and return new RedisConnectionFactory
}
}
这将有效地处理Redis不可用的情况
免责声明:我自己并没有测试这个,但基于我的ApacheGeode/GemFire示例,它确实有效。因此,也许,通过一些调整,这将满足您的需求。它也应该给你一些想法
希望这有帮助
干杯 我们可以使用任何断路器实现,在任何缓存故障的情况下使用数据库作为回退选项。使用断路器模式的优点是,一旦缓存启动,请求将自动路由回缓存,因此切换将无缝进行
您还可以配置在返回数据库之前要重试多少次,以及检查缓存是否恢复联机的频率
Spring cloud为hystrix和Resilience4j断路器实现提供了开箱即用的支持,并且易于与Spring boot应用程序集成
这只在开机时有效吗?也就是说,它将在启动时禁用缓存,但不会在运行时禁用?请详细说明如何实现上面的回退选项,如catch块中的ConcurrentHashMap。关于这是否仅在启动时有效。。。是的,以上代码当前就是这样配置的。但是,也可以在运行时禁用缓存。为此,您需要有效地使CacheManager
实现更加智能化。在这里使用Decorator软件设计模式是合适的。本质上,“缓存”启用方法的CacheManager
和返回的Cache
实现需要将不可用的缓存提供程序视为缓存未命中。@marios390-回退逻辑不一定需要在catch
块中。同样,当主缓存提供程序不在线时,您可以使用Decorator,甚至复合软件设计模式来使用默认的回退选项进行缓存。实际上,AOP使Spring缓存的划分成为可能。因此,您可以在拦截器链中包含另一个方面,以便在主缓存提供程序不在线时回退。辅助缓存提供程序选项必然位于拦截器链的后面。。。。。。在主缓存提供程序有机会尝试其工作之后。
@Confgiuration
@Conditional(RedisAvailableCondition.class);
class MyRedisConfiguration {
@Bean
RedisConnectionFactory redisConnectionFactory() {
// Construct and return new RedisConnectionFactory
}
}