Java 如果缓存服务器出现故障,是否可以使应用程序忽略缓存?

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启动应用程序:

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
    }
}