服务器之家:专注于服务器技术及软件下载分享
分类导航

Mysql|Sql Server|Oracle|Redis|MongoDB|PostgreSQL|Sqlite|DB2|mariadb|Access|数据库技术|

服务器之家 - 数据库 - Redis - @CacheEvict自动删Redis缓存的注意事项

@CacheEvict自动删Redis缓存的注意事项

2023-09-13 05:00未知服务器之家 Redis

一、前言 今天遇到了一个问题,就是关于@CacheEvict,这个相信大家都很熟悉了,是Spring整合一些缓存的专用注解,它和@Cacheable是一对。一个是新增缓存一个是删除缓存,搭配使用,不用自己手动删除! 今天遇到的问题是,@CacheE

@CacheEvict自动删Redis缓存的注意事项

一、前言

今天遇到了一个问题,就是关于@CacheEvict,这个相信大家都很熟悉了,是Spring整合一些缓存的专用注解,它和@Cacheable是一对。一个是新增缓存一个是删除缓存,搭配使用,不用自己手动删除!

今天遇到的问题是,@CacheEvict失效了,不会删除redis缓存。有两个方法都用了,一个会删除,一个不会删除。直接懵逼,随后和同事一起打断点发现了问题所在,其实还是自己没有看@CacheEvict注解的文档!

「是因为key的没有匹配上,我的方法参数有两个参数,并且没有指定key这样就匹配不到,无法删除!」

key注解注释:

默认值为 "",表示除非设置了自定义 keyGenerator ,否则所有方法参数都被视为键。

如果看了注释也不会浪费时间去找答案,但是查找问题的思路大家可以参考一下,我们也可以看看源码里面是怎么实现的!

二、找错过程

1、错误代码

@CacheEvict(value = {"warehouse:id"})
@GetMapping("/updateSubWarehouse")
public R updateSubWarehouse(@RequestParam("subWarehouseId") Integer subWarehouseId, @RequestParam("warehouseId") Integer warehouseId) {
    return warehouseService.updateSubWarehouse(subWarehouseId, warehouseId);
}

2、分析原因

我们看到@CacheEvict(value = {"warehouse:id"})只指定了value的值,也就是缓存的名称!

在看注解里的一个参数:

boolean allEntries() default false。

其一:我们看到这个是删除缓存的所有key,默认不开启,「不开启就会根据你传的名称和key去匹配删除缓存,然后删除!」

其二:如果接口是一个参数,不会有问题,这个接口是两个参数;redis默认把所有参数解析为SimpleKey作为key,有两个参数就会生成:SimpleKey [6267,467]。此时在去匹配,根本找不到,也就没有删除缓存了!

就是因为这样才会删除失败,当然简单粗暴的方式就是把allEntries = true,这样就会拿着缓存名称把所有key全部删除,不用在意生成的key了!

这样太粗暴,我们还是要选择第二种方式,两个参数及其以上时或者传的是对象时我们指定需要删除的key即可!

3、源码分析

是不是懂了,咱们再来debug源码一下:

源码类和方法大家可以自行debug一下:org.springframework.cache.interceptor.CacheAspectSupport#performCacheEvict。

第一次没有指定key会生成一个:

key = generateKey(context, result);得到:key = SimpleKey [6267,467]。

这个方法里面会把key和缓存名称拼接在一起去删除key:

doEvict(cache, key, operation.isBeforeInvocation())。

@CacheEvict自动删Redis缓存的注意事项

拼接key方法:createCacheKey(key)。

@CacheEvict自动删Redis缓存的注意事项

我们看一下一个参数的时候,key是怎么生成的:

我们看到一个参数的时候返回的是controller接口的参数类型,多个是返回的SimpleKey对象。

这样一个参数的就可以匹配到指定的key去删除!

@CacheEvict自动删Redis缓存的注意事项

三、解决方案

上面也说了,解决方案有两种:

  • @CacheEvict(value = {"warehouse:id"}, allEntries = true)。
  • @CacheEvict(value = {"warehouse:id"}, key = "#subWarehouseId")。

这样就完美解决了,其实还是没有把这个注解看明白,只知道有这么个东西可以删除缓存,出问题才发现。

延伸 · 阅读

精彩推荐
  • RedisRedis的配置、启动、操作和关闭方法

    Redis的配置、启动、操作和关闭方法

    今天小编就为大家分享一篇Redis的配置、启动、操作和关闭方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧 ...

    大道化简5312019-11-14
  • Redis详解Redis复制原理

    详解Redis复制原理

    与大多数db一样,Redis也提供了复制机制,以满足故障恢复和负载均衡等需求。复制也是Redis高可用的基础,哨兵和集群都是建立在复制基础上实现高可用的...

    李留广10222021-08-09
  • RedisRedis 事务知识点相关总结

    Redis 事务知识点相关总结

    这篇文章主要介绍了Redis 事务相关总结,帮助大家更好的理解和学习使用Redis,感兴趣的朋友可以了解下...

    AsiaYe8232021-07-28
  • RedisRedis如何实现数据库读写分离详解

    Redis如何实现数据库读写分离详解

    Redis的主从架构,能帮助我们实现读多,写少的情况,下面这篇文章主要给大家介绍了关于Redis如何实现数据库读写分离的相关资料,文中通过示例代码介绍...

    罗兵漂流记6092019-11-11
  • Redisredis 交集、并集、差集的具体使用

    redis 交集、并集、差集的具体使用

    这篇文章主要介绍了redis 交集、并集、差集的具体使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友...

    xiaojin21cen10152021-07-27
  • RedisRedis全量复制与部分复制示例详解

    Redis全量复制与部分复制示例详解

    这篇文章主要给大家介绍了关于Redis全量复制与部分复制的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用Redis爬虫具有一定的参考学习...

    豆子先生5052019-11-27
  • Redisredis实现排行榜功能

    redis实现排行榜功能

    排行榜在很多地方都能使用到,redis的zset可以很方便地用来实现排行榜功能,本文就来简单的介绍一下如何使用,具有一定的参考价值,感兴趣的小伙伴们...

    乘月归5022021-08-05
  • Redisredis中如何使用lua脚本让你的灵活性提高5个逼格详解

    redis中如何使用lua脚本让你的灵活性提高5个逼格详解

    这篇文章主要给大家介绍了关于redis中如何使用lua脚本让你的灵活性提高5个逼格的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具...

    一线码农5812019-11-18