spring一级缓存二级缓存和三级缓存的区别?spring二级缓存有什么用( 二 )


3、常用注解说明
@Cacheable:主要应用到查询数据的方法上 。
public @interface Cacheable { // cacheNames,CacheManager就是通过这个名称创建对应的Cache实现bean@AliasFor("cacheNames")String[] value() default {};@AliasFor("value")String[] cacheNames() default {}; // 缓存的key,支持SpEL表达式 。默认是使用所有参数及其计算的hashCode包装后的对象(SimpleKey)String key() default "";// 缓存key生成器,默认实现是SimpleKeyGeneratorString keyGenerator() default "";// 指定使用哪个CacheManager,如果只有一个可以不用指定String cacheManager() default "";// 缓存解析器String cacheResolver() default "";// 缓存的条件,支持SpEL表达式,当达到满足的条件时才缓存数据 。在调用方法前后都会判断String condition() default ""; // 满足条件时不更新缓存,支持SpEL表达式,只在调用方法后判断String unless() default "";// 回源到实际方法获取数据时,是否要保持同步,如果为false,调用的是Cache.get(key)方法;如果为true,调用的是Cache.get(key, Callable)方法boolean sync() default false;}
@CacheEvict:清除缓存,主要应用到删除数据的方法上 。相比Cacheable多了两个属性
public @interface CacheEvict { // ...相同属性说明请参考@Cacheable中的说明// 是否要清除所有缓存的数据,为false时调用的是Cache.evict(key)方法;为true时调用的是Cache.clear()方法boolean allEntries() default false;// 调用方法之前或之后清除缓存boolean beforeInvocation() default false;}
@CachePut:放入缓存,主要用到对数据有更新的方法上 。属性说明参考@Cacheable
@Caching:用于在一个方法上配置多种注解
@EnableCaching:启用Spring cache缓存,作为总的开关,在SpringBoot的启动类或配置类上需要加上此注解才会生效
三、使用二级缓存需要思考的一些问题?
我们知道关系数据库(Mysql)数据最终存储在磁盘上,如果每次都从数据库里去读取,会因为磁盘本身的IO影响读取速度,所以就有了
像redis这种的内存缓存 。
通过内存缓存确实能够很大程度的提高查询速度,但如果同一查询并发量非常的大,频繁的查询redis,也会有明显的网络IO上的消耗,
那我们针对这种查询非常频繁的数据(热点key),我们是不是可以考虑存到应用内缓存,如:caffeine 。
当应用内缓存有符合条件的数据时,就可以直接使用,而不用通过网络到redis中去获取,这样就形成了两级缓存 。
应用内缓存叫做一级缓存,远程缓存(如redis)叫做二级缓存 。
整个流程如下

spring一级缓存二级缓存和三级缓存的区别?spring二级缓存有什么用

文章插图
流程看着是很清新,但其实二级缓存需要考虑的点还很多 。
1.如何保证分布式节点一级缓存的一致性?
我们说一级缓存是应用内缓存,那么当你的项目部署在多个节点的时候,如何保证当你对某个key进行修改删除操作时,使其它节点
的一级缓存一致呢?
2.是否允许存储空值?
这个确实是需要考虑的点 。因为如果某个查询缓存和数据库中都没有,那么就会导致频繁查询数据库,导致数据库Down,这也是我们
常说的缓存穿透 。
但如果存储空值呢,因为可能会存储大量的空值,导致缓存变大,所以这个最好是可配置,按照业务来决定是否开启 。
3.是否需要缓存预热?
也就是说,我们会觉得某些key一开始就会非常的热,也就是热点数据,那么我们是否可以一开始就先存储到缓存中,避免缓存击穿 。
4.一级缓存存储数量上限的考虑?
既然一级缓存是应用内缓存,那你是否考虑一级缓存存储的数据给个限定最大值,避免存储太多的一级缓存导致OOM 。
5.一级缓存过期策略的考虑?
我们说redis作为二级缓存,redis是淘汰策略来管理的 。具体可参考redis的8种淘汰策略 。那你的一级缓存策略呢?就好比你设置一级缓存
数量最大为5000个,那当第5001个进来的时候,你是怎么处理呢?是直接不保存,还是说自定义LRU或者LFU算法去淘汰之前的数据?
6.一级缓存过期了如何清除?
我们说redis作为二级缓存,我们有它的缓存过期策略(定时、定期、惰性),那你的一级缓存呢,过期如何清除呢?
这里4、5、6小点如果说用我们传统的Map显然实现是很费劲的,但现在有更好用的一级缓存库那就是Caffeine 。
四、Caffeine 简介
Caffeine,一个用于Java的高性能缓存库 。
缓存和Map之间的一个根本区别是缓存会清理存储的项目 。


推荐阅读