Spring @Cacheable redis异常不影响正常业务方案

 更新时间:2021年02月19日 08:36:58   作者:神农L  
这篇文章主要介绍了Spring @Cacheable redis异常不影响正常业务方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

背景

项目中,使用@Cacheable进行数据缓存。发现:当redis宕机之后,@Cacheable注解的方法并未进行缓存冲突,而是直接抛出异常。而这样的异常会导致服务不可用。

原因分析

我们是通过@EnableCaching进行缓存启用的,因此可以先看@EnableCaching的相关注释

通过@EnableCaching的类注释可发现,spring cache的核心配置接口为:org.springframework.cache.annotation.CachingConfigurer

/**
 * Interface to be implemented by @{@link org.springframework.context.annotation.Configuration
 * Configuration} classes annotated with @{@link EnableCaching} that wish or need to
 * specify explicitly how caches are resolved and how keys are generated for annotation-driven
 * cache management. Consider extending {@link CachingConfigurerSupport}, which provides a
 * stub implementation of all interface methods.
 *
 * <p>See @{@link EnableCaching} for general examples and context; see
 * {@link #cacheManager()}, {@link #cacheResolver()} and {@link #keyGenerator()}
 * for detailed instructions.
 *
 * @author Chris Beams
 * @author Stephane Nicoll
 * @since 3.1
 * @see EnableCaching
 * @see CachingConfigurerSupport
 */
public interface CachingConfigurer {

 /**
 * Return the cache manager bean to use for annotation-driven cache
 * management. A default {@link CacheResolver} will be initialized
 * behind the scenes with this cache manager. For more fine-grained
 * management of the cache resolution, consider setting the
 * {@link CacheResolver} directly.
 * <p>Implementations must explicitly declare
 * {@link org.springframework.context.annotation.Bean @Bean}, e.g.
 * <pre class="code">
 * Configuration
 * EnableCaching
 * public class AppConfig extends CachingConfigurerSupport {
 *  Bean // important!
 *  Override
 *  public CacheManager cacheManager() {
 *   // configure and return CacheManager instance
 *  }
 *  // ...
 * }
 * </pre>
 * See @{@link EnableCaching} for more complete examples.
 */
 CacheManager cacheManager();

 /**
 * Return the {@link CacheResolver} bean to use to resolve regular caches for
 * annotation-driven cache management. This is an alternative and more powerful
 * option of specifying the {@link CacheManager} to use.
 * <p>If both a {@link #cacheManager()} and {@code #cacheResolver()} are set,
 * the cache manager is ignored.
 * <p>Implementations must explicitly declare
 * {@link org.springframework.context.annotation.Bean @Bean}, e.g.
 * <pre class="code">
 * Configuration
 * EnableCaching
 * public class AppConfig extends CachingConfigurerSupport {
 *  Bean // important!
 *  Override
 *  public CacheResolver cacheResolver() {
 *   // configure and return CacheResolver instance
 *  }
 *  // ...
 * }
 * </pre>
 * See {@link EnableCaching} for more complete examples.
 */
 CacheResolver cacheResolver();

 /**
 * Return the key generator bean to use for annotation-driven cache management.
 * Implementations must explicitly declare
 * {@link org.springframework.context.annotation.Bean @Bean}, e.g.
 * <pre class="code">
 * Configuration
 * EnableCaching
 * public class AppConfig extends CachingConfigurerSupport {
 *  Bean // important!
 *  Override
 *  public KeyGenerator keyGenerator() {
 *   // configure and return KeyGenerator instance
 *  }
 *  // ...
 * }
 * </pre>
 * See @{@link EnableCaching} for more complete examples.
 */
 KeyGenerator keyGenerator();

 /**
 * Return the {@link CacheErrorHandler} to use to handle cache-related errors.
 * <p>By default,{@link org.springframework.cache.interceptor.SimpleCacheErrorHandler}
 * is used and simply throws the exception back at the client.
 * <p>Implementations must explicitly declare
 * {@link org.springframework.context.annotation.Bean @Bean}, e.g.
 * <pre class="code">
 * Configuration
 * EnableCaching
 * public class AppConfig extends CachingConfigurerSupport {
 *  Bean // important!
 *  Override
 *  public CacheErrorHandler errorHandler() {
 *   // configure and return CacheErrorHandler instance
 *  }
 *  // ...
 * }
 * </pre>
 * See @{@link EnableCaching} for more complete examples.
 */
 CacheErrorHandler errorHandler();

}

该接口errorHandler方法可配置异常的处理方式。通过该方法上的注释可以发现,默认的CacheErrorHandler实现类是org.springframework.cache.interceptor.SimpleCacheErrorHandler

/**
 * A simple {@link CacheErrorHandler} that does not handle the
 * exception at all, simply throwing it back at the client.
 *
 * @author Stephane Nicoll
 * @since 4.1
 */
public class SimpleCacheErrorHandler implements CacheErrorHandler {

 @Override
 public void handleCacheGetError(RuntimeException exception, Cache cache, Object key) {
 throw exception;
 }

 @Override
 public void handleCachePutError(RuntimeException exception, Cache cache, Object key, Object value) {
 throw exception;
 }

 @Override
 public void handleCacheEvictError(RuntimeException exception, Cache cache, Object key) {
 throw exception;
 }

 @Override
 public void handleCacheClearError(RuntimeException exception, Cache cache) {
 throw exception;
 }
}

SimpleCacheErrorHandler类注释上说明的很清楚:对cache的异常不做任何处理,直接将该异常抛给客户端。因此默认的情况下,redis服务器异常后,直接就阻断了正常业务

解决方案

通过上面的分析可知,我们可以通过自定义CacheErrorHandler来干预@Cacheable的异常处理逻辑。具体代码如下:

public class RedisConfig extends CachingConfigurerSupport {

  /**
   * redis数据操作异常处理。该方法处理逻辑:在日志中打印出错误信息,但是放行。
   * 保证redis服务器出现连接等问题的时候不影响程序的正常运行
   */
  @Override
  public CacheErrorHandler errorHandler() {
    return new CacheErrorHandler() {
      @Override
      public void handleCachePutError(RuntimeException exception, Cache cache,
                      Object key, Object value) {
        handleRedisErrorException(exception, key);
      }

      @Override
      public void handleCacheGetError(RuntimeException exception, Cache cache,
                      Object key) {
        handleRedisErrorException(exception, key);
      }

      @Override
      public void handleCacheEvictError(RuntimeException exception, Cache cache,
                       Object key) {
        handleRedisErrorException(exception, key);
      }

      @Override
      public void handleCacheClearError(RuntimeException exception, Cache cache) {
        handleRedisErrorException(exception, null);
      }
    };
  }

  protected void handleRedisErrorException(RuntimeException exception, Object key) {
    log.error("redis异常:key=[{}]", key, exception);
  }
}

到此这篇关于Spring @Cacheable redis异常不影响正常业务方案的文章就介绍到这了,更多相关Spring @Cacheable redis异常内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 关于springBoot yml文件的list读取问题总结(亲测)

    关于springBoot yml文件的list读取问题总结(亲测)

    这篇文章主要介绍了关于springBoot yml文件的list读取问题总结,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-12-12
  • SpringBoot中自定义注解实现参数非空校验的示例

    SpringBoot中自定义注解实现参数非空校验的示例

    这篇文章主要介绍了SpringBoot中自定义注解实现参数非空校验,帮助大家更好的理解和使用springboot框架,感兴趣的朋友可以了解下
    2020-11-11
  • Josephus环的四种解法(约瑟夫环)基于java详解

    Josephus环的四种解法(约瑟夫环)基于java详解

    这篇文章主要介绍了Josephus环的四种解法(约瑟夫环)基于java详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-09-09
  • Java的MyBatis框架项目搭建与hellow world示例

    Java的MyBatis框架项目搭建与hellow world示例

    MyBatis框架为Java程序的数据库操作带来了很大的便利,这里我们就从最基础的入手,来看一下Java的MyBatis框架项目搭建与hellow world示例,需要的朋友可以参考下
    2016-06-06
  • 详解Spring Cloud 熔断机制--断路器

    详解Spring Cloud 熔断机制--断路器

    这篇文章主要介绍了详解Spring Cloud 熔断机制--断路器,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-04-04
  • Java @Value(

    Java @Value("${xxx}")取properties时中文乱码的解决

    这篇文章主要介绍了Java @Value("${xxx}")取properties时中文乱码的解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-07-07
  • spring cloud consul注册的服务报错critical的解决

    spring cloud consul注册的服务报错critical的解决

    这篇文章主要介绍了spring cloud consul注册的服务报错critical的解决,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2019-03-03
  • Java 如何解决跨域问题

    Java 如何解决跨域问题

    这篇文章主要介绍了Java 如何解决跨域问题,帮助大家更好的理解和学习使用Java,感兴趣的朋友可以了解下
    2021-03-03
  • String.replaceAll方法详析(正则妙用)

    String.replaceAll方法详析(正则妙用)

    这篇文章主要给大家介绍了关于String.replaceAll方法,正则妙用的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-07-07
  • JAVA像SQL一样对List对象集合进行排序

    JAVA像SQL一样对List对象集合进行排序

    这篇文章主要介绍了JAVA像SQL一样对List对象集合进行排序的实现方法,文中讲解非常细致,代码帮助大家更好的理解和学习,感兴趣的朋友可以了解下
    2020-07-07

最新评论