caffeine学习笔记

在项目中使用了caffeine,本文将会介绍其工具的原理

1.caffenine的缓存淘汰策略

Window-TinyLFU

1.新增缓存数据首先写入 Window Cache 区域。当 Window Cache 空间满时,LRU 算法发挥作用,最久未被访问的缓存项会被移出 Window Cache 。这个被移出的缓存项称为 Candidate (候选项),将面临 2 种情况:

如果 Probation Cache 未满,从 Window Cache 中移出的缓存项会直接写入 Probation Cache 中;

如果 Probation Cache 已满,则进入到 TinyLFU 过滤器,与 Protected Cache 移出的缓存项比较。根据 TinyLFU 算法确定该缓存项是淘汰还是写入 Probation Cache。

2.Probation Cache 中的缓存项的访问频率达到一定次数后,就会晋升到 Protected Cache 中。(Ps. 到 Protected 保护区的都是经过 2 层选拔的真热门数据)如果 Protected Cache 也满了,根据 LRU 算法,最久未被访问的缓存项会被移出 Protected Cache ,降级成为 Candidate ,进入到 TinyLFU 过滤器,与 Window Cache 移出的缓存项作比较,根据 TinyLFU 算法确定该缓存项是淘汰还是写入到 Probation Cache 中。

3.此时把目光聚焦到 TinyLFU 过滤器,它汇聚了来自 Window Cache 、Protected Cache 和 Probation Cache 3 个区域中被移出的缓存项。其中,从 Window Cache 和 Protected Cache 中移出的缓存项称为 Candidate ;而从 Probation Cache 中移出的缓存项称为 Victim (受害者) 。这 3 个区域移出的缓存项都是各自区域中最久未被使用的数据,在 TinyLFU 过滤器中进行竞争,竞争算法如下:

如果 Candidate 的访问频率 > Victim 的访问频率,则直接淘汰 Victim ;

如果 Candidate 的访问频率 <= Victim 的访问频率,此时分为两种情况:

如果 Candidate 的访问频率 < 5 ,则淘汰 Candidate ;

如果 Candidate 的访问频率 >= 5 ,则在 Candidate 和 Victim 中随机淘汰一个。

获胜者被称为 Winner ,就会被写入到 Probation Cache 中。

从上面的 W-TinyLFU 的原理描述可知,Caffeine 综合了 LFU 和 LRU 的优势,将不同特性的缓存项存入不同的缓存区域,最近刚产生的缓存项进入 Window Cache 区,不会被淘汰;访问频率高的缓存项进入 Protected Cache 区,也不会淘汰;介于这两者之间的缓存项存在 Probation 区,当缓存空间满了时,Probation 区的缓存项会根据访问频率判断是保留还是淘汰。

通过这种机制,很好的平衡了访问频率和访问时间新鲜程度两个维度因素,尽量将新鲜的缓存项和访问频率高的缓存项都保留在缓存中。同时在维护缓存项访问频率时,引入计数器饱和和衰减 (Count-Min Sketch, 下面会说) 机制,即节省了存储资源,也能较好的处理稀疏流量、短时超热点流量等传统 LRU 和 LFU 无法很好处理的场景。

W-TinyLFU 算法

W-TinyLFU 算法使用 Count-Min Sketch 算法存储访问频率,极大地节省了空间。

看到一个通俗解释:如果需要记录一个值,那我们需要通过多种 Hash 算法对其进行处理,然后在对应的 Hash 算法的记录中 +1。那为什么需要多种 Hash 算法呢?由于这是一个压缩算法必定会出现冲突,比如我们建立一个 byte 的数组,通过计算出每个数据的 Hash 的位置。比如张三和李四,他们两有可能 Hash 值都是相同,比如都是 1 。那 byte[1] 这个位置就会增加相应的频率,张三访问 1 万次,李四访问 1 次,那 byte[1] 这个位置就是 1万零1 ,如果取李四的访问评率的时候就会取出是 1万零1 ,但是李四命名只访问了1次啊!为了解决这个问题,所以用了多个 Hash 算法,可以理解为 long[][] 二维数组的一个概念。比如在第一个 Hash 算法中,张三和李四冲突了,但是在第二个,第三个 Hash 算法中很大的概率不冲突,比如一个算法大概有 1% 的概率冲突,那四个算法一起冲突的概率是 1% 的四次方。通过这个模式我们取李四的访问率的时候取所有算法中,李四访问最低频率的次数。所以他的名字叫 Count-Min Sketch 。

2.caffeine的数据结构

复制代码
final ConcurrentHashMap<Object, Node<K, V>> data;

写入数据:

将节点添加到策略和数据存储中。如果找到现有节点,则在允许的情况下更新其值

根据不同的更新策略,计算缓存过期时间后数据塞入map中。数据写入后,增加定时任务。注意此时当未自定义线程池时,将会使用默认的forkjoinpool中的线程池,默认线程池可能会影响主程序的执行效率。

@NonNull
  Executor getExecutor() {
    return (executor == null) ? ForkJoinPool.commonPool() : executor;
  }

淘汰数据:

操作ConcurrentHashMap类型的data数据,

相关推荐
蝴蝶不愿意4 小时前
《苍穹外卖》项目学习记录-Day7添加购物车
学习
Lovely Ruby4 小时前
DeepSeek-R1本地部署笔记
笔记
我的青春不太冷5 小时前
【实战篇章】深入探讨:服务器如何响应前端请求及后端如何查看前端提交的数据
运维·服务器·前端·学习
power-辰南6 小时前
人工智能学习(四)之机器学习基本概念
人工智能·学习·机器学习
影林握雪6 小时前
M|哪吒之魔童闹海
经验分享·笔记·其他·生活
白嫖勇者7 小时前
C++基础学习
学习
LightspeedResearch8 小时前
冲刺一区!挑战7天完成一篇趋势性分析GBD DAY1-7
学习
Lorcian8 小时前
web前端12--表单和表格
前端·css·笔记·html5·visual studio code
Lyrig~8 小时前
【Convex Optimization Stanford】Lec5. Duality 对偶问题
学习·凸优化
字节全栈_kYu12 小时前
微信小程序视频点播在线视频学习系统 毕业设计 课程设计(1)首页_微信小程序视频功能设计流程图
学习·微信小程序·课程设计