spring一级缓存二级缓存和三级缓存的区别?spring二级缓存有什么用( 三 )
1、写入缓存策略
Caffeine有三种缓存写入策略:手动、同步加载和异步加载 。
2、缓存值的清理策略
Caffeine有三种缓存值的清理策略:基于大小、基于时间和基于引用 。
基于容量:当缓存大小超过配置的大小限制时会发生回收 。
基于时间:
- 写入后到期策略 。
- 访问后过期策略 。
- 到期时间由 Expiry 实现独自计算 。
基于引用:启用基于缓存键值的垃圾回收 。
- Java种有四种引用:强引用,软引用,弱引用和虚引用,caffeine可以将值封装成弱引用或软引用 。
- 软引用:如果一个对象只具有软引用,则内存空间足够,垃圾回收器就不会回收它;如果内存空间不足了,就会回收这些对象的内存 。
- 弱引用:在垃圾回收器线程扫描它所管辖的内存区域的过程中,一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会
回收它的内存 。
3、统计
Caffeine提供了一种记录缓存使用统计信息的方法,可以实时监控缓存当前的状态,以评估缓存的健康程度以及缓存命中率等,方便后
续调整参数 。
4、高效的缓存淘汰算法
缓存淘汰算法的作用是在有限的资源内,尽可能识别出哪些数据在短时间会被重复利用,从而提高缓存的命中率 。常用的缓存淘汰算法有
LRU、LFU、FIFO等 。
FIFO:先进先出 。选择最先进入的数据优先淘汰 。LRU:最近最少使用 。选择最近最少使用的数据优先淘汰 。LFU:最不经常使用 。选择在一段时间内被使用次数最少的数据优先淘汰 。
LRU(Least Recently Used)算法认为最近访问过的数据将来被访问的几率也更高 。
LRU通常使用链表来实现,如果数据添加或者被访问到则把数据移动到链表的头部,链表的头部为热数据,链表的尾部如冷数据,当
数据满时,淘汰尾部的数据 。
LFU(Least Frequently Used)算法根据数据的历史访问频率来淘汰数据,其核心思想是“如果数据过去被访问多次,那么将来被访问
【spring一级缓存二级缓存和三级缓存的区别?spring二级缓存有什么用】的频率也更高” 。根据LFU的思想,如果想要实现这个算法,需要额外的一套存储用来存每个元素的访问次数,会造成内存资源的浪费 。
Caffeine采用了一种结合LRU、LFU优点的算法:W-TinyLFU,其特点:高命中率、低内存占用 。
5、其他说明
Caffeine的底层数据存储采用ConcurrentHashMap 。因为Caffeine面向JDK8,在jdk8中ConcurrentHashMap增加了红黑树,在hash冲突
严重时也能有良好的读性能 。
五、基于Spring Cache实现二级缓存(Caffeine+Redis)
前面说了,使用了redis缓存,也会存在一定程度的网络传输上的消耗,所以会考虑应用内缓存,但有点很重要的要记住:
应用内缓存可以理解成比redis缓存更珍惜的资源,所以,caffeine 不适用于数据量大,并且缓存命中率极低的业务场景,如用户维度的缓存 。
当前项目针对应用都部署了多个节点,一级缓存是在应用内的缓存,所以当对数据更新和清除时,需要通知所有节点进行清理缓存的操作 。
可以有多种方式来实现这种效果,比如:zookeeper、MQ等,但是既然用了redis缓存,redis本身是有支持订阅/发布功能的,所以就
不依赖其他组件了,直接使用redis的通道来通知其他节点进行清理缓存的操作 。
当某个key进行更新删除操作时,通过发布订阅的方式通知其它节点进行删除该key本地的一级缓存就可以了 。
具体具体项目代码这里就不再粘贴出来了,这样只粘贴如何引用这个starter包 。
1、maven引入使用
<dependency> <groupId>com.jincou</groupId> <artifactId>redis-caffeine-cache-starter</artifactId> <version>1.0.0</version> </dependency>
2、application.yml
添加二级缓存相关配置
# 二级缓存配置# 注:caffeine 不适用于数据量大,并且缓存命中率极低的业务场景,如用户维度的缓存 。请慎重选择 。l2cache: config: # 是否存储空值,默认true,防止缓存穿透 allowNullValues: true # 组合缓存配置 composite: # 是否全部启用一级缓存,默认false l1AllOpen: false # 是否手动启用一级缓存,默认false l1Manual: true # 手动配置走一级缓存的缓存key集合,针对单个key维度 l1ManualKeySet: - userCache:user01 - userCache:user02 - userCache:user03 # 手动配置走一级缓存的缓存名字集合,针对cacheName维度 l1ManualCacheNameSet: - userCache - goodsCache # 一级缓存 caffeine: # 是否自动刷新过期缓存 true 是 false 否 autoRefreshExpireCache: false # 缓存刷新调度线程池的大小 refreshPoolSize: 2 # 缓存刷新的频率(秒) refreshPeriod: 10 # 写入后过期时间(秒) expireAfterWrite: 180 # 访问后过期时间(秒) expireAfterAccess: 180 # 初始化大小 initialCapacity: 1000 # 最大缓存对象个数,超过此数量时之前放入的缓存将失效 maximumSize: 3000 # 二级缓存 redis: # 全局过期时间,单位毫秒,默认不过期 defaultExpiration: 300000 # 每个cacheName的过期时间,单位毫秒,优先级比defaultExpiration高 expires: {userCache: 300000,goodsCache: 50000} # 缓存更新时通知其他节点的topic名称 默认 cache:redis:caffeine:topic topic: cache:redis:caffeine:topic
推荐阅读
- Spring容器这些扩展点你都清楚了吗?
- Springboot默认的错误页是如何工作及工作原理你肯定不知道?
- springboot 结合 logback 设置
- Spring中的SmartLifecycle作用
- Springboot配置文件加载路径及使用方式你真的都了解了吗?
- 手撸了一个 Spring MVC 框架
- 一个基于spring boot的Java开源商城系统
- excel下拉菜单如何设置一级二级-excel 下拉一二三级菜单-
- 教大家简单搭建一个SpringBoot项目
- 手把手带你编译Spring框架源码,让你的学习事半功倍