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

网友投稿 956 2023-02-11

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

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.

*

*

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.

*

Implementations must explicitly declare

* {@link org.springframework.context.annotation.Bean @Bean}, e.g.

*

* Configuration

* EnableCaching

* public class AppConfig extends CachingConfigurerSupport {

* Bean // important!

* Override

* public CacheManager cacheManager() {

* // configure and return CacheManager instance

* }

* // ...

* }

*

* 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.

*

If both a {@link #cacheManager()} and {@code #cacheResolver()} are set,

* the cache manager is ignored.

*

Implementations must explicitly declare

* {@link org.springframework.context.annotation.Bean @Bean}, e.g.

*

* Configuration

* EnableCaching

* public class AppConfig extends CachingConfigurerSupport {

* Bean // important!

* Override

* public CacheResolver cacheResolver() {

* // configure and return CacheResolver instance

* }

* // ...

* }

*

* 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.

*

* Configuration

* EnableCaching

* public class AppConfig extends CachingConfigurerSupport {

* Bean // important!

* Override

* public KeyGenerator keyGenerator() {

* // configure and return KeyGenerator instance

* }

* // ...

* }

*

* See @{@link EnableCaching} for more complete examples.

*/

KeyGenerator keyGenerator();

/**

* Return the {@link CacheErrorHandler} to use to handle cache-related errors.

*

By default,{@link org.springframework.cache.interceptor.SimplxxKOBiYTjeCacheErrorHandhttp://ler}

* is used and simply throws the exception back at the client.

*

Implementations must explicitly declare

* {@link org.springframework.context.annotation.Bean @Bean}, e.g.

*

* Configuration

* EnableCaching

* public class AppConfig extends CachingConfigurerSupport {

* Bean // important!

* Override

* public CacheErrorHandler errorHandler() {

* // configure and return CacheErrorHandler instance

* }

* // ...

* }

*

* See @{@link EnableCaching} for more complete examples.

*/

CacheErrorHandler errorHandler();

}

该接口errorHandler方法可配置异常的处理方式。通过该方法上的注释可以发现,默认的CaxxKOBiYTjcheErrorHandler实现类是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);

}

}

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:web前端安全书籍推荐(web前端书籍下载)
下一篇:web前端安全书籍(web前端书籍下载)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~