提问者:小点点

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


我有一个具有以下属性的Spring引导应用程序:

spring.cache.type: redis
spring.redis.host: <hostname>
spring.redis.port: <hostport>

现在,如果远程主机发生故障,应用程序也会因连接错误而失败。在这种情况下,我的缓存不是应用程序的核心,但它仅用于性能,我希望Spring简单地绕过它并转到数据库检索其数据。

我发现这可以通过定义一个自定义的errorHandler方法来实现,但是为了做到这一点,我必须实现CachingConfigrer bean…但是这也迫使我覆盖每个方法(例如缓存管理器、缓存解析器、ecc。)。

@Configuration
public class CacheConfiguration implements CachingConfigurer{

@Override
public CacheManager cacheManager() {
    // TODO Auto-generated method stub
    return null;
}

@Override
public CacheResolver cacheResolver() {
    // TODO Auto-generated method stub
    return null;
}
...
@Override
public CacheErrorHandler errorHandler() {
    // the only method I need, maybe
    return null;
}

我想避免这种情况…我只需要一种方法来告诉Spring“缓存崩溃了,但没关系:假装你根本没有缓存”


共3个答案

匿名用户

@phate-当然!我刚刚回答了一个相关的问题(可能),使用Apache Geode或Pivotal GemFire作为Spring Boot应用程序中的缓存提供程序和Spring的缓存抽象。

在那篇文章中,我没有完全禁用缓存,而是将GemFire/Geode切换为仅在本地模式下运行(GemFire/Geode可能的配置)。然而,如果需要的话,可以应用相同的技术来完全禁用缓存。

本质上,在Spring Boot和Spring通常开始评估应用程序的配置之前,您需要一个预处理步骤。

在我的示例中,我实现了一个自定义Spring条件来检查集群(即服务器)的可用性。然后,我将条件应用于我的@Configuration类。

在Spring Boot的情况下,Spring Boot在应用程序的类路径上有效地看到(以及在此处看到)Redis和Spring Data Redis时,会为Redis应用自动配置(作为存储和缓存提供程序)。因此,本质上,只有当“条件”为真时,Redis才被启用为缓存提供程序,主要是您的应用程序配置声明了RedisConnectionFactorybean,这是您的责任。

那么,这看起来像什么?

就像我的Apache Geode

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不可用的情况下将缓存呈现为无操作。NONE在这里进行了更详细的解释。

当然,您也可以使用回退缓存选项,使用其他一些缓存提供程序(例如简单的ConCurrentHashMap,但我将其作为练习留给您)。向前…

然后,在您定义了RedisConnectionFactorybean的Spring Boot应用程序配置类中(正如Spring Boot的自动配置所期望的那样),您使用Spring的@条件注释添加此自定义条件,如下所示:

@Confgiuration
@Conditional(RedisAvailableCondition.class);
class MyRedisConfiguration {

    @Bean
    RedisConnectionFactory redisConnectionFactory() {
        // Construct and return new RedisConnectionFactory
    }
}

这应该可以有效地处理Redis不可用的情况。

免责声明:我自己没有测试这个,但基于我的Apache Geode/Pivotal GemFire示例,它确实有效。所以,也许,通过一些调整,这将满足您的需求。它还应该为您提供一些想法。

希望这有帮助!

干杯!

匿名用户

我们可以使用任何断路器实现来使用数据库作为任何缓存故障的后备选项。使用断路器模式的优点是,一旦您的缓存启动,请求将自动路由回您的缓存,因此切换无缝进行。

您还可以配置在回退到数据库之前要重试多少次,以及要检查缓存是否在线备份的频率。

Spring cloud为hystrix和Resilience4j断路器实现提供开箱即用的支持,并且易于与Spring启动应用程序集成。

https://spring.io/projects/spring-cloud-circuitbreaker
https://resilience4j.readme.io/docs/circuitbreaker

匿名用户

我必须实现CachingConfigrer bean…但这也迫使我覆盖每个方法(例如缓存管理器、缓存解析器、ecc。)

相反,您可以简单地扩展CachingConfigrerSupport并仅覆盖errorHandler()方法,返回一个自定义的CacheErrorHandler,其方法实现是无操作的。请参阅https://stackoverflow.com/a/68072419/1527469