博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
java cache定时过期,本地缓存高性能之王Caffeine
阅读量:5940 次
发布时间:2019-06-19

本文共 4894 字,大约阅读时间需要 16 分钟。

前言

随着互联网的高速发展,市面上也出现了越来越多的网站和app。我们判断一个软件是否好用,用户体验就是一个重要的衡量标准。比如说我们经常用的微信,打开一个页面要十几秒,发个语音要几分钟对方才能收到。相信这样的软件大家肯定是都不愿意用的。软件要做到用户体验好,响应速度快,

Tips: Spring5(SpringBoot2)开始用Caffeine取代guava.详见官方信息SPR-13797 https://jira.spring.io/browse/SPR-13797

官方性能比较

以下测试都是基于jmh测试的,官网地址 测试为什么要基于jmh测试,可以参考知乎上R回答

在HotSpot VM上跑microbenchmark切记不要在main()里跑循环计时就完事。这是典型错误。重要的事情重复三遍:请用JMH,请用JMH,请用JMH。除非非常了解HotSpot的实现细节,在main里这样跑循环计时得到的结果其实对一般程序员来说根本没有任何意义,因为无法解释。

8个线程读,100%的读操作

dbdfdfa130e38c48eea98e76830269d6.png

6个线程读,2个线程写,也就是75%的读操作,25%的写操作。

dbdfdfa130e38c48eea98e76830269d6.png

8个线程写,100%的写操作

dbdfdfa130e38c48eea98e76830269d6.png

对比结论

可以从数据看出来Caffeine的性能都比Guava要好。然后Caffeine的API的操作功能和Guava是基本保持一致的,并且 Caffeine为了兼容之前是Guava的用户,做了一个Guava的Adapter给大家使用也是十分的贴心。

如何使用

在 pom.xml 中添加 caffeine 依赖

com.github.ben-manes.caffeine

caffeine

2.8.2

创建对象

Cache cache = Caffeine.newBuilder()

.initialCapacity(100)//初始大小

.maximumSize(200)//最大数量

.expireAfterWrite(3, TimeUnit.SECONDS)//过期时间

.build();

创建参数介绍

initialCapacity: 初始的缓存空间大小maximumSize: 缓存的最大数量maximumWeight: 缓存的最大权重expireAfterAccess: 最后一次读或写操作后经过指定时间过期expireAfterWrite: 最后一次写操作后经过指定时间过期refreshAfterWrite: 创建缓存或者最近一次更新缓存后经过指定时间间隔,刷新缓存weakKeys: 打开key的弱引用weakValues:打开value的弱引用softValues:打开value的软引用recordStats:开发统计功能

注意: expireAfterWrite和expireAfterAccess同时存在时,以expireAfterWrite为准。maximumSize和maximumWeight不可以同时使用。

添加数据

Caffeine 为我们提供了手动、同步和异步这几种填充策略。 下面我们来演示下手动填充策略吧,其他几种如果大家感兴趣的可以去官网了解下

Cache cache = Caffeine.newBuilder()

.build();

cache.put("java金融", "java金融");

System.out.println(cache.getIfPresent("java金融"));

自动添加(自定义添加函数)

public static void main(String[] args) {

Cache cache = Caffeine.newBuilder()

.build();

// 1.如果缓存中能查到,则直接返回

// 2.如果查不到,则从我们自定义的getValue方法获取数据,并加入到缓存中

String val = cache.get("java金融", k -> getValue(k));

System.out.println(val);

}

/**

* 缓存中找不到,则会进入这个方法。一般是从数据库获取内容

* @param k

* @return

*/

private static String getValue(String k) {

return k + ":value";

}

过期策略

Caffeine 为我们提供了三种过期策略 ,分别是基于大小(size-based)、基于时间(time-based)、基于引用(reference-based)

基于大小(size-based)

LoadingCache cache = Caffeine.newBuilder()

// 最大容量为1

.maximumSize(1)

.build(k->getValue(k));

cache.put("java金融1","java金融1");

cache.put("java金融2","java金融2");

cache.put("java金融3","java金融3");

cache.cleanUp();

System.out.println(cache.getIfPresent("java金融1"));

System.out.println(cache.getIfPresent("java金融2"));

System.out.println(cache.getIfPresent("java金融3"));

运行结果如下:淘汰了两个只剩下一个。

null

null

java金融3

基于时间(time-based)

Caffeine提供了三种定时驱逐策略:

expireAfterWrite(long, TimeUnit)

在最后一次写入缓存后开始计时,在指定的时间后过期。

LoadingCache cache =  Caffeine.newBuilder()

// 最大容量为1

.maximumSize(1)

.expireAfterWrite(3, TimeUnit.SECONDS)

.build(k->getValue(k));

cache.put("java金融","java金融");

Thread.sleep(1*1000);

System.out.println(cache.getIfPresent("java金融"));

Thread.sleep(1*1000);

System.out.println(cache.getIfPresent("java金融"));

Thread.sleep(1*1000);

System.out.println(cache.getIfPresent("java金融"));

运行结果第三秒的时候取值为空。

java金融

java金融

null

expireAfterAccess

在最后一次读或者写入后开始计时,在指定的时间后过期。假如一直有请求访问该key,那么这个缓存将一直不会过期。

LoadingCache cache =  Caffeine.newBuilder()

// 最大容量为1

.maximumSize(1)

.expireAfterAccess(3, TimeUnit.SECONDS)

.build(k->getValue(k));

cache.put("java金融","java金融");

Thread.sleep(1*1000);

System.out.println(cache.getIfPresent("java金融"));

Thread.sleep(1*1000);

System.out.println(cache.getIfPresent("java金融"));

Thread.sleep(1*1000);

System.out.println(cache.getIfPresent("java金融"));

Thread.sleep(3001);

System.out.println(cache.getIfPresent("java金融"));

运行结果:读和写都没有的情况下,3秒后才过期,然后就输出了null。

java金融

java金融

java金融

null

expireAfter(Expiry)

在expireAfter中需要自己实现Expiry接口,这个接口支持expireAfterCreate,expireAfterUpdate,以及expireAfterRead了之后多久过期。注意这个是和expireAfterAccess、expireAfterAccess是互斥的。这里和expireAfterAccess、expireAfterAccess不同的是,需要你告诉缓存框架,他应该在具体的某个时间过期,获取具体的过期时间。

LoadingCache cache = Caffeine.newBuilder()

// 最大容量为1

.maximumSize(1)

.removalListener((key, value, cause) ->

System.out.println("key:" + key + ",value:" + value + ",删除原因:" + cause))

.expireAfter(new Expiry() {

@Override

public long expireAfterCreate(@NonNull String key, @NonNull String value, long currentTime) {

return currentTime;

}

@Override

public long expireAfterUpdate(@NonNull String key, @NonNull String value, long currentTime, @NonNegative long currentDuration) {

return currentTime;

}

@Override

public long expireAfterRead(@NonNull String key, @NonNull String value, long currentTime, @NonNegative long currentDuration) {

return currentTime;

}

})

.build(k -> getValue(k));

删除

单个删除:Cache.invalidate(key)批量删除:Cache.invalidateAll(keys)删除所有缓存项:Cache.invalidateAll

总结

本文只是对Caffeine的一个简单使用的介绍,它还有很多不错的东西,比如缓存监控、事件监听、W-TinyLFU算法(高命中率、低内存占用)感兴趣的同学可以去官网查看。

结束

由于自己才疏学浅,难免会有纰漏,假如你发现了错误的地方,还望留言给我指出来,我会对其加以修正。如果你觉得文章还不错,你的转发、分享、赞赏、点赞、留言就是对我最大的鼓励。感谢您的阅读,十分欢迎并感谢您的关注。

参考

https://www.itcodemonkey.com/article/9498.html

https://juejin.im/post/5dede1f2518825121f699339

https://www.cnblogs.com/CrankZ/p/10889859.html

https://blog.csdn.net/hy245120020/article/details/78080686

https://github.com/ben-manes/caffeine

注明:本文来自投稿,不代表服务器文档网立场,如若转载,请注明出处:https://www.fwqwd.com/4568.html

你可能感兴趣的文章
Apache Storm 官方文档 —— 常用模式
查看>>
聊聊JVM的年轻代
查看>>
lvm逻辑卷管理
查看>>
VS2010不能断点/下断的问题
查看>>
[Android]权限处理
查看>>
Spark bind on port 0. Attempting port 1 问题解决
查看>>
兼容所有浏览器的复制到剪切板功能,悬浮层不能复制问题解决
查看>>
day 20 第一阶段考试总结
查看>>
我的友情链接
查看>>
Centos 7.5 部署DNS
查看>>
yum简介
查看>>
cp讲解
查看>>
MariaDB Galera Cluster 部署(如何快速部署MariaDB集群)
查看>>
如何在 Swift 语言下使用 iOS Charts API 制作漂亮图表?
查看>>
论代码审查的重要性
查看>>
「docker实战篇」python的docker爬虫技术-导学(一)
查看>>
linux日志基础介绍
查看>>
如何关闭SElinux
查看>>
处理器之MMU(三)
查看>>
172.16.82.0/25的含义,IP段,掩码
查看>>