做一个单纯的程序汪,分享干货,聊聊人生。
微信公众号:后端架构进阶
关注我发现更多的干货,微服务、Spring源码、JVM、SpringCloud Alibaba、K8S等。
互联网软件神速发展,用户的体验度是判断一个软件好坏的重要原因,所以缓存就是必不可少的一个神器。
在多线程高并发场景中往往是离不开cache的,需要根据不同的应用场景来需要选择不同的cache,比如分布式缓存如redis、memcached,还有本地(进程内)缓存如ehcache、GuavaCache、Caffeine。
说起Guava Cache,很多人都不会陌生,它是Google Guava工具包中的一个非常方便易用的本地化缓存实现,基于LRU算法实现,支持多种缓存过期策略。
但是,Guava Cache的性能一定是最好的吗?也许,曾经,它的性能是非常不错的。但所谓长江后浪推前浪,总会有更加优秀的技术出现。今天,我就来介绍一个比Guava Cache性能更高的缓存框架:Caffeine。
一、性能比较
场景一、8个线程读,100%的读操作
场景二、6个线程读,2个线程写,也就是75%的读操作,25%的写操作
场景三:8个线程写,100%的写操作
看到这里,是不是应该反手给个666?而且这是官方给的测试结果。虽说Caffeine是基于Guava Cache改版。但是这样的数据绝对能勾起你的兴趣。
那么,问题来了,怎么使用呢?别急,客官,听我细说。
二、集成使用
在我们的项目中的使用也是非常简单,首先引入依赖,我这里版本号用的是最新的。可以按照自己的需求选择版本号。
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
<version>3.0.4</version>
</dependency>
加载代码的简单测试如下所示,通过CacheBuilder来构建缓存。设置初始化值、最大值、过期时间以及没查到数据的时候的加载逻辑。
public static void main(String[] args) {
LoadingCache<String, String> build = CacheBuilder
.newBuilder()
.initialCapacity(1) # 初始大小
.maximumSize(100) # 最大容量
.expireAfterWrite(1, TimeUnit.DAYS) # 过期时间
.build(new CacheLoader<String, String>() {
//当调用get取值的时候,如果key没有对应的值,就调用这个方法进行加载
@Override
public String load(String key) {
return "";
}
});
}
三、过期策略
在Caffeine中分为两种缓存,一个是有界缓存,一个是无界缓存,无界缓存不需要过期并且没有界限。
有界缓存提供了三个过期API
- expireAfterWrite:代表着写了之后多久过期。(上面列子就是这种方式)
- expireAfterAccess:代表着最后一次访问了之后多久过期。
- expireAfter:在expireAfter中需要自己实现Expiry接口,这个接口支持create、update以及access之后多久过期。
最后这个API和前面两个API互斥。需要你告诉缓存框架,他应该在具体的某个时间过期,也就是通过前面的重写create、update以及access的方法,获取具体的过期时间。
四、更新策略
Caffeine提供了refreshAfterWrite()方法来让我们进行写后多久更新策略。
LoadingCache<String, String> build = CacheBuilder
.newBuilder()
.refreshAfterWrite(1, TimeUnit.DAYS) # 多久后刷新
.build(new CacheLoader<String, String>() {
@Override
public String load(String key) {
return "";
}
});
}
上面这种方式到一天后也不会刷新,因为必有在1天后这个缓存再次访问才能刷新,如果没人访问,那么永远也不会刷新。
自动刷新他是怎么做的呢?自动刷新只存在读操作之后,也就是我们 afterRead() 这个方法,其中有个方法叫 refreshIfNeeded(),他会根据你是同步还是异步然后进行刷新处理。
五、统计
使用Caffeine.recordStats(),您可以打开统计信息收集。Cache.stats() 方法返回提供统计信息的CacheStats。
Cache<Key, Graph> graphs = Caffeine.newBuilder()
.maximumSize(1000)
.recordStats()
.build();
统计信息的值中包含的数据如下:
- hitRate():返回命中与请求的比率
- hitCount(): 返回命中缓存的总数
- evictionCount():缓存逐出的数量
- averageLoadPenalty():加载新值所花费的平均时间
用了之后感觉真的爽,从GuavaCache切换过来的成本也很低。快去试试吧!喜欢记得关注我哟~
之前的文章都做了总结,感兴趣直接查看,传送门:
总结
以上就是之前的内容的总结和分享,感谢各位大佬的 关注、点赞和 收藏 !
微信公众号:后端架构进阶
更多文章正在赶来,喜欢记得给我点个 👍 ,感谢支持!
公众号文章同步更新!关注我,不迷路!