美文网首页
spring-boot-starter-data-redis使用

spring-boot-starter-data-redis使用

作者: vayci | 来源:发表于2023-08-16 11:12 被阅读0次

    问题说明

    在开发过程中,某个方法上进行了以下注解,将返回数据缓存起来。

        @Cacheable(
                value = CacheKey.DEPT_ALL,
                unless="#result==null")
    

    由于业务需要,在另一个Class中,调用某个方法时需要清除这个缓存,于是注解上:

        @CacheEvict(
                value = CacheKey.DEPT_ALL
         )
    

    然而在调用缓存清除的方法时,发现缓存并没有清除,注解没生效。

    问题排查

    看网上有说法说对于缓存操作要放到同一个Java文件中,不能分开到两个类。但是这个说法一看感觉就不正确,于是进行源码分析排查。

    定位到spring-boot-starter-data-redis的核心类 org.springframework.cache.interceptor.CacheInterceptor

    可以排查到针对注解方法实现的操作位于org.springframework.cache.interceptor.CacheAspectSupport#execute()方法中

    代码片段:

            // Collect any explicit @CachePuts
            collectPutRequests(contexts.get(CachePutOperation.class), cacheValue, cachePutRequests);
    
            // Process any collected put requests, either from @CachePut or a @Cacheable miss
            for (CachePutRequest cachePutRequest : cachePutRequests) {
                cachePutRequest.apply(cacheValue);
            }
    
            // Process any late evictions
            processCacheEvicts(contexts.get(CacheEvictOperation.class), false, cacheValue);
    

    这里分别处理了缓存写入和缓存失效的相关操作。

    分别断点查看调用缓存写入和缓存失效时操作的Redis Key值,发现缓存写入时,Key是"SimpleKey";而缓存失效时,Key是我方法传入的一堆参数。问题产生的原因就已经明确了,是因为写入和销毁的key值不一致,导致缓存没有销毁成功。

    问题修复

    查看@CacheEvict的文档里面对Key值说明:

    Default is "", meaning all method parameters are considered as a key, unless a custom keyGenerator has been set.
    

    不进行配置时,默认是将方法的所有参数作为key。

    修复方案也比较简单了,由于这里对key值没有要求,是固定的缓存key。将注解的key加一个固定字符串即可。

            @Cacheable(
                value = CacheKey.DEPT_USER_COUNT,
                unless="#result==null",
                key="'ALL'")
    
        @CacheEvict(value = CacheKey.DEPT_USER_COUNT, key = "'ALL'")
    

    总结:注解@CacheEvict失效,首先排查Key值与写入的Key值是否一致。

    相关文章

      网友评论

          本文标题:spring-boot-starter-data-redis使用

          本文链接:https://www.haomeiwen.com/subject/fvmkmdtx.html