Caffeine使用指南

Caffeine基于java8的高性能,接近最优的缓存库。Caffeine提供的内存缓存使用参考Google guava的API。Caffeine是基于Google guava和 ConcurrentLinkedHashMap的设计经验上改进的成果。

Caffeine可以通过建造者模式灵活的组合以下特性:

  1. 通过异步自动加载实体到缓存中
  2. 基于大小的回收策略
  3. 基于时间的回收策略
  4. 自动刷新
  5. key自动封装虚引用
  6. value自动封装弱引用或软引用
  7. 实体过期或被删除的通知
  8. 写入外部资源
  9. 统计累计访问缓存

加载策略

Caffeine提供了3种加载策略:手动加载,同步加载,异步加载

手动加载

Cache<Key, Graph> cache = Caffeine.newBuilder().expireAfterWrite(10, TimeUnit.MINUTES).maximumSize(10_000).build();
// 检索一个entry,如果没有则为null
Graph graph = cache.getIfPresent(key);
// 检索一个entry,如果entry为null,则通过key创建一个entry并加入缓存
graph = cache.get(key, k -> createExpensiveGraph(key));
// 插入或更新一个实体
cache.put(key, graph);
// 移除一个实体
cache.invalidate(key);

同步加载

构造Cache时候,build方法传入一个CacheLoader实现类。实现load方法,通过key加载value。

LoadingCache<Key, Graph> cache = Caffeine.newBuilder().maximumSize(10_000).expireAfterWrite(10, TimeUnit.MINUTES).build(key -> createExpensiveGraph(key));
//如果缓存种没有对应的value,通过createExpensiveGraph方法加载
Graph graph = cache.get(key);Map<Key, Graph> graphs = cache.getAll(keys);

异步加载

AsyncLoadingCache<Key, Graph> cache = Caffeine.newBuilder().maximumSize(10_000).expireAfterWrite(10, TimeUnit.MINUTES).buildAsync((key, executor) -> createExpensiveGraphAsync(key, executor));
CompletableFuture<Graph> graph = cache.get(key);
CompletableFuture<Map<Key, Graph>> graphs = cache.getAll(keys);

AsyncLoadingCache 是 LoadingCache 的变体, 可以异步计算实体在一个线程池(Executor)上并且返回 CompletableFuture.

回收策略

Caffeine提供了3种回收策略:基于大小回收,基于时间回收,基于引用回收

基于大小回收

// 基于实体数量淘汰实体
LoadingCache<Key, Graph> graphs = Caffeine.newBuilder().maximumSize(10_000).build(key -> createExpensiveGraph(key));// 通过权重来计算,每个实体都有不同的权重,总权重到达最高时淘汰实体。
LoadingCache<Key, Graph> graphs = Caffeine.newBuilder().maximumWeight(10_000).weigher((Key key, Graph graph) -> graph.vertices().size()).build(key -> createExpensiveGraph(key));

到达最大大小时淘汰最近最少使用的实体

基于时间回收

  1. 实体被访问之后,在实体被读或被写后的一段时间后过期
LoadingCache<Key, Graph> graphs = Caffeine.newBuilder().expireAfterAccess(5, TimeUnit.MINUTES).build(key -> createExpensiveGraph(key));
  1. 基于写之后,在实体被写入后的一段时间后过期
LoadingCache<Key, Graph> graphs = Caffeine.newBuilder().expireAfterWrite(10, TimeUnit.MINUTES).build(key -> createExpensiveGraph(key));
  1. 自定义策略Expiry,可以自定义在实体被读,被更新,被创建后的时间过期。
LoadingCache<Key, Graph> graphs = Caffeine.newBuilder().expireAfter(new Expiry<Key, Graph>() {public long expireAfterCreate(Key key, Graph graph, long currentTime) {// Use wall clock time, rather than nanotime, if from an external resourcelong seconds = graph.creationDate().plusHours(5).minus(System.currentTimeMillis(), MILLIS).toEpochSecond();return TimeUnit.SECONDS.toNanos(seconds);}public long expireAfterUpdate(Key key, Graph graph, long currentTime, long currentDuration) {return currentDuration;}public long expireAfterRead(Key key, Graph graph,long currentTime, long currentDuration) {return currentDuration;}}).build(key -> createExpensiveGraph(key));

基于引用回收

java种有四种引用:强引用,软引用,弱引用和虚引用,caffeine可以将值封装成弱引用或软引用。
软引用:如果一个对象只具有软引用,则内存空间足够,垃圾回收器就不会回收它;如果内存空间不足了,就会回收这些对象的内存。
弱引用:弱引用的对象拥有更短暂的生命周期。在垃圾回收器线程扫描它所管辖的内存区域的过程中,一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存

LoadingCache<Key, Graph> graphs = Caffeine.newBuilder().weakKeys().weakValues().build(key -> createExpensiveGraph(key));LoadingCache<Key, Graph> graphs = Caffeine.newBuilder().softValues().build(key -> createExpensiveGraph(key));

自动刷新

LoadingCache<Key, Graph> graphs = Caffeine.newBuilder().maximumSize(10_000).refreshAfterWrite(1, TimeUnit.MINUTES).build(key -> createExpensiveGraph(key));

在写后的持续时间过后,调用createExpensiveGraph刷新

移除通知

Cache<Key, Graph> graphs = Caffeine.newBuilder().removalListener((Key key, Graph graph, RemovalCause cause) ->System.out.printf("Key %s was removed (%s)%n", key, cause)).build();

通过removalListener添加实体移除监听器

写到外部存储

通过CacheWriter 可以将缓存回写的外部存储中。

LoadingCache<Key, Graph> graphs = Caffeine.newBuilder().writer(new CacheWriter<Key, Graph>() {@Override public void write(Key key, Graph graph) {// 写入到外部存储或二级缓存}@Override public void delete(Key key, Graph graph, RemovalCause cause) {// 删除外部存储或者二级缓存}}).build(key -> createExpensiveGraph(key));

使用场景

  1. 缓存同步数据库
  2. 多级缓存同步

注意,CacheWriter不能与弱键或AsyncLoadingCache一起使用

统计缓存使用情况

Cache<Key, Graph> graphs = Caffeine.newBuilder().maximumSize(10_000).recordStats().build();

通过使用Caffeine.recordStats(), 可以转化成一个统计的集合. 通过 Cache.stats() 返回一个CacheStats。CacheStats提供以下统计方法

hitRate(): 返回缓存命中率
evictionCount(): 缓存回收数量
averageLoadPenalty(): 加载新值的平均时间

Caffeine入门相关推荐

  1. Caffeine入门使用

    <Caffeine入门使用> -> <Caffeine基础源码解析> -> <Caffeine 驱逐算法> 一.概况 就一般的互联网行业中的应用而言,目 ...

  2. 【Caffeine入门】浅谈缓存框架Caffeine

    Caffeine是一个基于Java8的高性能缓存框架,号称趋于完美.Caffeine受启发于Guava Cache的API,使用API和Guava是一致的.它借鉴了Guava Cache和Concur ...

  3. HM-SpringCloud微服务系列11.1【多级缓存的意义JVM进程缓存】

    HM-SpringCloud微服务系列11:多级缓存-高级篇 1. 什么是多级缓存 多级缓存是亿级流量的缓存方案 浏览器访问静态资源时,优先读取浏览器本地缓存 访问非静态资源(ajax查询数据)时,访 ...

  4. Caffeine缓存快速入门

    目录 Caffeine组件的特点是: 基本使用 手动数据添加和删除 数据加载 过期数据的同步加载(一) 过期数据的同步加载(二) Caffeine异步缓存加载 缓存数据驱逐: 数量驱逐策略: 权重驱逐 ...

  5. 小白都能看懂的缓存入门

    缓存是程序员必须了解的技术,无论是前端.后端还是客户端,大到复杂的系统架构,小到 CPU 或是芯片,都少不了缓存的影子. 下面只需 5 分钟,带你入门缓存技术. 什么是缓存? 缓存(Cache)本意是 ...

  6. Spring Boot(一)入门篇

    Spring Boot干货系列:(一)优雅的入门篇 前言 Spring一直是很火的一个开源框架,在过去的一段时间里,Spring Boot在社区中热度一直很高,所以决定花时间来了解和学习,为自己做技术 ...

  7. Spring Boot入门到牛X

    Spring Boot入门到牛X 1.Spring Boot 项目下载地址:https://download.csdn.net/download/weixin_39549656/10287664 1. ...

  8. Spring Boot (16)---优雅的入门篇

    Spring Boot (16)---优雅的入门篇 Spring一直是很火的一个开源框架,在过去的一段时间里,Spring Boot在社区中热度一直很高,所以决定花时间来了解和学习,为自己做技术储备. ...

  9. SpringBoot的Cacheable缓存入门

    因为工作需要,最近开始学习SpringBoot.要使用缓存,就搜索了下SpringBoot的缓存方案,有自带的ConcurrentLinkedHashMap,还有主流的Guava.Caffeine.E ...

最新文章

  1. 只需2040张图片,训练视觉Transformer:南大吴建鑫团队提出IDMM
  2. string转换为bigdecimal_SO面试题09:如何将String转换为Int?
  3. Java 基础学习(Markdown语法)
  4. 昕灵感应流行坊(Shop.25941.Cn)^_^全新开张
  5. 由于开发者通过接口修改了菜单配置_开发者说:Seata 0.7.0 版本,你 get 'Metrics' 技能了吗?...
  6. Linux 命令之 yum -- 基于 RPM 的软件包管理器
  7. linux系统get命令详解,Ubuntu Linux系统下apt-get命令详解
  8. mybatis 逆向工程生成的 Example 类的使用
  9. 怎么查linux上谁删了文件,如何在 Linux 下快速找到被删除的文件?
  10. 发明导诊机器人团队_牛!这个平均年龄21岁的团队竟然发明偏瘫康复机器人
  11. @ Before,@ BeforeClass,@ BeforeEach和@BeforeAll之间的区别
  12. Linux下如何查看高CPU占用率线程 专题
  13. Web - JSON基础讲解
  14. x射线计算机断层成像_医疗保健中的深度学习-X射线成像(第4部分-类不平衡问题)...
  15. window10+cuda+cudnn下载
  16. QT实现串口调试助手(一)
  17. 研究生能合作发表论文吗?
  18. 计算机专业相关的国家认证,国内认证的计算机证书有哪些?
  19. TSP_旅行商问题 - 遗传算法(四)
  20. Flutter 字体设置加粗

热门文章

  1. 调试 GPS 1.575G干扰无法搜星问题
  2. 各类3D打印技术的制造工艺原理
  3. 廖雪峰python教程整理笔记_python小白01廖雪峰python教程笔记
  4. vue+Element做表格的批量增加
  5. XTransfer又双叒叕拿奖,XTransfer外贸收款这么靠谱吗?
  6. 持续交付之一——软件交付的问题
  7. JavaScript变量详解加实例教程
  8. Redis五种数据结构及实现原理
  9. c语言程序 出圈游戏,【出圈】 (C语言代码)
  10. SOC的定义、适用性和组成