Caffeine Cache解析(一):接口设计与TinyLFU
Caffeine is a high performance Java caching library providing a near optimal hit rate.
- 自动加载value, 支持异步加载
- 基于size的eviction:frequency and recency
- 基于时间的过期策略:last access or last write
- 异步更新value
- key支持weak reference
- value支持weak reference和soft reference
- 淘汰(或移除)通知
- todo
- 缓存获取数据统计
Caffeine的性能benchmark可参考Caffeine Benchmarks,
可以看到Caffeine在不同读写比的情况下, 吞吐量比Guava Cache和Jdk内置的HashMap都有较大提升。
接下来了解下Caffeine的使用、接口设计和TinyLFU简介。
使用
// manual cache,Cache-Aside模式Cache<String, String> cache = Caffeine.newBuilder().expireAfterWrite(Duration.ofHours(1)).build();// null表示不存在key@Nullable String val = cache.getIfPresent("hello");if (val == null) {cache.put("hello", "world");}// key不存在则走后面的loading functionString val2 = cache.get("hello", key -> "world");// loading cache,Read-Through模式LoadingCache<String, String> loadingCache = Caffeine.newBuilder().expireAfterAccess(Duration.ofMinutes(10)).maximumSize(2000).build(new CacheLoader<String, String>() {@Overridepublic @Nullable String load(@NonNull String s) throws Exception {// your loading logicreturn "";}});// 不存在会自动loadingString val3 = loadingCache.get("hello");
接口设计
CacheCache按不同维度划分:
- kv是否有限:Bounded or Unbounded,判断参见方法
com.github.benmanes.caffeine.cache.Caffeine#isBounded,大部分场景都使用BoundedCache - 是否自动loading: ManualCache和LoadingCache
- 是否异步: Cache和AsyncCache
对应接口UML如下(实现类只画出了BoundedCache),其接口和类均位于com.github.benmanes.caffeine.cache包下:

可以看到,核心的kv存储是放在了LocalCache接口(本质是一个ConcurrentMap)下,而其他的Loading和Async接口在存储基础上附加了自动加载value和异步加载的能力,以同步接口为例,接口能力如下:
Cache: 提供缓存基础能力,包含设置、读取、失效、获取缓存统计数据等功能;LoadingCache: 提供自动加载能力,在Cache基础上新增不存在则loading value的读取以及refresh方法;LocalCache: 提供核心存储能力,线程安全和原子能力保证,继承自java.util.concurrent.ConcurrentMap;LocalManualCache: 基于LocalCache做存储的非自动Loading Cache;LocalLoadingCache: 继承自LocalManualCache,新增Loading功能。
关于以上接口的一个关键抽象实现类BoundedLocalCache,其作用解释如下:
This class performs a best-effort bounding of a ConcurrentHashMap using a page-replacement algorithm to determine which entries to evict when the capacity is exceeded.
TinyLFU & W-TinyLFU
在看BoundedLocalCache类前先来了解下TinyLFU & W-TinyLFU算法,
算法出自论文:TinyLFU: A Highly Efficient Cache Admission Policy
- admission policy:控制一个元素是否能进入缓存
- eviction policy:当缓存满了时选择哪一个元素剔除缓存
论文中提出的TinyLFU指的是admission policy,
TinyLFU可以和 LRU 、SLRU 的eviction policy组合。
比如 论文中使用W-TinyLFU + LRU + SLRU的组合进行实验:
Window Tiny LFU (W-TinyLFU) … consists of two cache areas.
The main cache employs the SLRU eviction policy and TinyLFU admission policy
while the window cache employs an LRU eviction policy without any admission policy.

可以看到 W-TinyLFU 的main cache area 使用 TinyLFU 作为 admission policy。
TinyLFU 在 LFU的基础上 加了Tiny,而Tiny体现在counter计数(和frequency正相关) 的记录上。
通常大部分缓存的元素访问频率都会很小,如果使用integer来记录counter计数,会导致空间浪费,因此
TinyLFU 借助 approximate counting scheme 来记录counter计数,其原理和bloom filter类似,而 schema的具体实现有:
Counting Bloom FilterCM-Sketch: Caffeine中使用该实现,参见类com.github.benmanes.caffeine.cache.FrequencySketch,论文可参考:An Improved Data Stream Summary: The Count-Min Sketch and its Applications
Caffeine中的CM-Sketch使用4bit记录counter次数,最大只能到15,
并使用long[]类型存储,一个元素可存储16个计数器,long[]即相当于论文中的二维数组。
此外还增加了一个DoorKeeper即一个Bloom Filter来优先存储读取次数为1的元素,次数大于1的才会进入CM-Sketch结构中。
此外,TinyLFU利用Freshness Mechanism保证TinyLFU计数器记录的次数不会无限制扩大:
Every time we add an item to the approximation sketch, we increment a counter.
Once this counter reaches the sample size (W), we divide it and all other counters in the
approximation sketch by 2.
对应的可以在FrequencySketch类的increment方法中找到reset方法的调用:
// This class maintains a 4-bit CountMinSketch.
// The maximum frequency of an element is limited to 15 (4-bits)
// and an aging process periodically halves the popularity of all elements.
final class FrequencySketch<E> {...int sampleSize;int size;public void ensureCapacity(@NonNegative long maximumSize) {...sampleSize = (maximumSize == 0) ? 10 : (10 * maximum);if (sampleSize <= 0) {sampleSize = Integer.MAX_VALUE;}size = 0;}// 计数器次数小于15时才会增加计数器public void increment(@NonNull E e) {...boolean added = ...if (added && (++size == sampleSize)) {reset();}}...
}
相关文章:
Caffeine Cache解析(一):接口设计与TinyLFU
Caffeine is a high performance Java caching library providing a near optimal hit rate. 自动加载value, 支持异步加载基于size的eviction:frequency and recency基于时间的过期策略:last access or last write异步更新valuekey支持weak referenceva…...
深入探索LINUX中AWK命令:强大的文本处理工具
深入探索LINUX中AWK命令:强大的文本处理工具 AWK 是一种编程语言,专为文本和数据处理设计,它以其强大的文本处理能力和简洁的语法在 Unix/Linux 系统中占据了重要地位。AWK 程序由一系列的模式(pattern)和动作(action)组成,对于输…...
数字化转型:解决项目管理困境的新路径
在当今这个飞速发展的数字化时代,企业如同在汹涌波涛中航行的船只,承受着前所未有的变革压力。而作为企业运作核心环节之一的项目管理,同样面临着巨大的挑战。 传统项目管理模式中的种种问题,犹如顽固的礁石,阻碍着项目…...
Arthas常用的命令(三)--monitor、jad 、stack
monitor:监控方法的执行情况 监控指定类中方法的执行情况 用来监视一个时间段中指定方法的执行次数,成功次数,失败次数,耗时等这些信息 参数说明 方法拥有一个命名参数 [c:],意思是统计周期(cycle of ou…...
Power BI之常用DAX函数使用介绍——提供数据源练习
前述: 本次使用数据是包含产品表、客户表、区域表、销售订单表的一份销售订单数据,数据源链接如下: 链接:https://pan.baidu.com/s/1micl_09hFrgz2aUBERkeZg 提取码:y17e 一、CALCULATE 1.语法结构 语法结构CALCUL…...
SQL-触发器(trigger)的详解以及代码演示
一、触发器的概念 触发器是一种特殊的存储过程,但是触发器不存在输入和输出参数,所以不能被显式的去调用,而是与特定的表相关联,当表中的数据发生变化时,触发器被激活并执行其定义的SQL代码。触发器可以是行级触发器&…...
【devops】x-ui 实现一键安装 x-ray 打造高速国际冲浪 | xray管理平台
一、部署X-UI篇 1、Github 地址&说明 github地址如下: https://github.com/FranzKafkaYu/x-ui?tabreadme-ov-file 2、一键部署 2.1、更新并安装curl #Ubuntu、Deibian系统 apt update && apt upgrade -y apt install curl -y #CentOS7 系统 yum…...
Linux系统编程——进程标识、进程创建
一、进程标识(pid) 每个进程都有一个非负整数形式的唯一编号,即 PID。PID 在任何时刻都是唯一的,但是可以重用,当进程终止并被回收以后,其 PID 就可以为其它进程所用。进程的 PID 由系统内核根据延迟重用算…...
【超级福利】openMind开源实习来袭,奖励高达万元,解锁你的AI实践新篇章!
亲爱的小伙伴们,是不是梦想着能在真实的项目中大展拳脚,却又苦于找不到合适的舞台?别担心,OpenI启智社区携手openMind Library工具链,为你量身打造了一场开源实习盛宴,保证让你的学习不再无聊,技…...
React JSX 使用条件语句渲染UI的两种写法
只针对函数组件 1. 第一种写法: function App({ id }) {return id1? <h1>hello</h1> : <h1>world</h1>; } 或者: function App({ id }) {return (<h1>{id1 && "hello" || id2 && "wo…...
谷歌-BERT-第四步:模型部署
1 需求 需求1:基于gradio实现大模型的WEB UI交互界面 2 接口 3 示例 import gradio as gr from transformers import *classifier pipeline("text-classification", model"./model", tokenizer"./model")gr.Interface.from_pipel…...
猫咪化身蒲公英,浮毛满屋乱飞,有哪些宠物空气净化器值得购买?
不掉毛的猫咪究竟是谁在养? 当初去朋友家玩,被猫咪捕获芳心,没多久自己也领养了一只。没想到啊,这就意味着要和猫毛纠缠一辈子了。平时白天上班不在家,它就在一边跑动一边掉毛,回到家我都能推断它的行动路…...
端到端的开源OCR模型:GOT-OCR-2.0,支持场景文本、文档、乐谱、图表、数学公式等内容识别!
今天给大家分享一个端到端的开源 OCR 模型,号称 OCR 2.0! 支持场景文本、文档、乐谱、图表、数学公式等内容识别,拿到了 BLEU 0.972 高分。 从给出的演示图来看,一些非常复杂的数学公式都能正确的识别,颇为强大。模型…...
自注意力机制self-attention中QKV矩阵的含义
自注意力机制(Self-Attention)是Transformer模型的核心组件,其中Q、K、V矩阵分别代表查询(Query)、键(Key)、值(Value)。它们的作用和含义可以通过信息匹配过程来理解。在…...
【前端】Bootstrap:栅格系统 (Grid System)
Bootstrap的栅格系统是该框架的核心部分之一,能够让开发者轻松创建响应式网页布局,适配各种屏幕尺寸和设备。栅格系统通过将页面划分为12列的布局结构,开发者可以根据内容的重要性和设计需求灵活控制元素的宽度和排列。 在这篇文章中&#x…...
一文读懂,SSL证书怎么验签安装使用?
SSL证书目前已经有越来越多的企业网站开始使用,安装SSL证书后,原有的http协议将会变成安全性更好的https加密协议,这对保护用户的信息安全,保障企业及用户的利益起着重要作用。 一张SSL证书的获取,需要经历不少环节&a…...
Mysql(八) --- 视图
文章目录 前言1.什么是视图?2.创建视图3. 使用视图4. 修改数据4.1.注意事项 5. 删除视图6.视图的优点 前言 前面我们学习了索引,这次我们来学习视图 1.什么是视图? 视图是一个虚拟的表,它是基于一个或多个基本表或其他视图的查询…...
SQL注入原理、类型、危害与防御
SQL注入的原理概念 SQL注入是一种常见的网络攻击技术,攻击者通过在Web应用程序的输入字段中注入恶意构造的SQL代码,以欺骗后端数据库执行非预期的SQL命令。这种攻击可以导致数据泄露、权限提升、数据篡改甚至系统瘫痪。SQL注入可以分为多种类型…...
第2讲 数据库系统的结构抽象与演变
基本内容 数据库系统的标准结构?数据模型?数据库系统的演变与发展?重难点 一组概念的区分:三级模式两层映像,物理独立性和逻辑独立性一组概念的区分:数据→模式→数据模型几种数据模型的差异:网状/层次模型→关系模型→数据模型数据库系统的标准结构 (1)数据库系统的分…...
Git创建开发分支命名规则
git checkout -b feature/branchname 和 git checkout -b branchname 这两条命令的主要区别在于新分支的命名。 主要区别 分支命名: git checkout -b feature/branchname:新分支的名字是 feature/branchname,表示该分支属于一个特性开发&…...
C++初阶-list的底层
目录 1.std::list实现的所有代码 2.list的简单介绍 2.1实现list的类 2.2_list_iterator的实现 2.2.1_list_iterator实现的原因和好处 2.2.2_list_iterator实现 2.3_list_node的实现 2.3.1. 避免递归的模板依赖 2.3.2. 内存布局一致性 2.3.3. 类型安全的替代方案 2.3.…...
Linux链表操作全解析
Linux C语言链表深度解析与实战技巧 一、链表基础概念与内核链表优势1.1 为什么使用链表?1.2 Linux 内核链表与用户态链表的区别 二、内核链表结构与宏解析常用宏/函数 三、内核链表的优点四、用户态链表示例五、双向循环链表在内核中的实现优势5.1 插入效率5.2 安全…...
基于ASP.NET+ SQL Server实现(Web)医院信息管理系统
医院信息管理系统 1. 课程设计内容 在 visual studio 2017 平台上,开发一个“医院信息管理系统”Web 程序。 2. 课程设计目的 综合运用 c#.net 知识,在 vs 2017 平台上,进行 ASP.NET 应用程序和简易网站的开发;初步熟悉开发一…...
从零实现富文本编辑器#5-编辑器选区模型的状态结构表达
先前我们总结了浏览器选区模型的交互策略,并且实现了基本的选区操作,还调研了自绘选区的实现。那么相对的,我们还需要设计编辑器的选区表达,也可以称为模型选区。编辑器中应用变更时的操作范围,就是以模型选区为基准来…...
Objective-C常用命名规范总结
【OC】常用命名规范总结 文章目录 【OC】常用命名规范总结1.类名(Class Name)2.协议名(Protocol Name)3.方法名(Method Name)4.属性名(Property Name)5.局部变量/实例变量(Local / Instance Variables&…...
GitHub 趋势日报 (2025年06月08日)
📊 由 TrendForge 系统生成 | 🌐 https://trendforge.devlive.org/ 🌐 本日报中的项目描述已自动翻译为中文 📈 今日获星趋势图 今日获星趋势图 884 cognee 566 dify 414 HumanSystemOptimization 414 omni-tools 321 note-gen …...
ios苹果系统,js 滑动屏幕、锚定无效
现象:window.addEventListener监听touch无效,划不动屏幕,但是代码逻辑都有执行到。 scrollIntoView也无效。 原因:这是因为 iOS 的触摸事件处理机制和 touch-action: none 的设置有关。ios有太多得交互动作,从而会影响…...
【HarmonyOS 5 开发速记】如何获取用户信息(头像/昵称/手机号)
1.获取 authorizationCode: 2.利用 authorizationCode 获取 accessToken:文档中心 3.获取手机:文档中心 4.获取昵称头像:文档中心 首先创建 request 若要获取手机号,scope必填 phone,permissions 必填 …...
云原生安全实战:API网关Kong的鉴权与限流详解
🔥「炎码工坊」技术弹药已装填! 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 一、基础概念 1. API网关(API Gateway) API网关是微服务架构中的核心组件,负责统一管理所有API的流量入口。它像一座…...
FFmpeg avformat_open_input函数分析
函数内部的总体流程如下: avformat_open_input 精简后的代码如下: int avformat_open_input(AVFormatContext **ps, const char *filename,ff_const59 AVInputFormat *fmt, AVDictionary **options) {AVFormatContext *s *ps;int i, ret 0;AVDictio…...
