源码地址:
org.springframework.cache.interceptor.CacheAspectSupport
org.springframework.cache.interceptor.AbstractCacheInvoker
immediate属性就是beforeInvocation, 即是否立即删除, cache.clear() 则是执行删除缓存, cache.invalidate()最后也会执行clear方法
beforeInvocation
默认在@CacheEvict 方法成功执行之后再清除,这时候就会存在一个问题,也许你的注解方法成功执行了删除操作,但是后续代码抛出异常导致未能清除缓存,下次查询时依旧从缓存中去读取,这时查询到的结果值是删除操作之前的值,而设置beforeInvocation=true之后当执行这个方法之前执行清除缓存的操作,这样不管这个方法执行成功与否,该缓存都将不存在 (aop成功的前提下,缓存才会删除,有可能执行缓存清除失败)
allEntries
慎用注解的allEntries属性, 因为allEntries会根据传入的value属性拼成"${value}*"模糊匹配的字符串进行模糊匹配删除
org.springframework.data.redis.cache.RedisCache
this.cacheWriter.clean 方法执行的是 DefaultRedisCacheWriter.class#clean 方法, 这是spring-data-redis提供的默认实现类, 可以通过重写这个类改变redis操作逻辑
org.springframework.data.redis.cache.DefaultRedisCacheWriter
redis会先通过keys命令获取所有键值,然后再删除
redis在使用keys时会扫描全表,这会导致短时间内Redis的cpu和内存飙高,且因为Redis是单线程执行操作,所以同时会导致Redis请求阻塞
PS: redis 6.0 的多线程只是前面的协议解读部分使用了多线程,底层增删改查还是用的单线程
所以生产环境要慎用甚至禁用掉@CacheEvict , 通过调整缓存结构来规避使用keys命令
完
如果帮到你,请点个赞吧 O(∩_∩)O~