Java本地缓存Caffeine的简单使用
Caffeine基本介绍
Caffeine 是基于 JAVA 8 的高性能本地缓存库。并且在 spring5 (springboot 2.x) 后,spring 官方放弃了 Guava,而使用了性能更优秀的 Caffeine 作为默认缓存组件。
Caffeine是在Guava Cache的基础上做一层封装,性能有明显提高,二者同属于内存级本地缓存。
使用Caffeine后无需使用Guava Cache,从并发的角度来讲,Caffeine明显优于Guava,原因是使用了Java 8最新的StampedLock锁技术。
本地缓存与分布式缓存对应,缓存进程和应用进程同属于一个JVM,数据的读、写在一个进程内完成。
本地缓存没有网络开销,访问速度很快。
Caffeine提供灵活的结构来创建缓存,并且有以下特性:
- 自动加载条目到缓存中,可选异步方式
- 可以基于大小剔除
- 可以设置过期时间,时间可以从上次访问或上次写入开始计算
- 异步刷新
- keys自动包装在弱引用中
- values自动包装在弱引用或软引用中
- 条目剔除通知
- 缓存访问统计
简单使用
导入pom依赖
<dependency> <groupId>com.github.ben-manes.caffeine</groupId> <artifactId>caffeine</artifactId> <version>2.6.2</version> </dependency>
入门案例
// 构建cache对象 Cache<String, String> cache = Caffeine.newBuilder().build(); // 存数据 cache.put("k1", "v1"); // 取数据 String v1 = cache.getIfPresent("k1"); System.out.println("k1 = " + v1); // 取数据,包含两个参数: // 参数一:缓存的key // 参数二:Lambda表达式,表达式参数就是缓存的key,方法体是查询数据库的逻辑 // 优先根据key查询JVM缓存,如果未命中,则执行参数二的Lambda表达式 String defaultkey = cache.get("k2", key -> { // 根据key去数据库查询数据 return "v2"; }); System.out.println("k2 = " + defaultkey);
配置案例
public static LoadingCache<Long, User> loadingCache = Caffeine.newBuilder() // 初始的缓存空间大小 .initialCapacity(5) // 缓存的最大条数 .maximumSize(10) .expireAfterWrite(4, TimeUnit.SECONDS) .expireAfterAccess(10, TimeUnit.SECONDS) .refreshAfterWrite(6, TimeUnit.SECONDS) .recordStats() //设置缓存的移除通知 .removalListener(new RemovalListener<Long, User>() { @Override public void onRemoval(@Nullable Long key, @Nullable User user, @NonNull RemovalCause removalCause) { System.out.printf("Key: %s ,值:%s was removed!原因 (%s) \n", key, user, removalCause); } }) .build(id -> { System.out.println("缓存未命中,从数据库加载,用户id:" + id); return User.builder().id(id).userName("Lily").age(new Random().nextInt(20)).build(); });
参数说明:
- initialCapacity 初始的缓存空间大小
- maximumSize 缓存的最大条数
- maximumWeight 缓存的最大权重
- expireAfterAccess 最后一次写入或访问后,经过固定时间过期
- expireAfterWrite 最后一次写入后,经过固定时间过期
- refreshAfterWrite 写入后,经过固定时间过期,下次访问返回旧值并触发刷新
- weakKeys 打开 key 的弱引用
- weakValues 打开 value 的弱引用
- softValues 打开 value 的软引用
- recordStats 缓存使用统计
- expireAfterWrite 和 expireAfterAccess 同时存在时,以 expireAfterWrite 为准。
- weakValues 和 softValues 不可以同时使用。
- maximumSize 和 maximumWeight 不可以同时使用。
清除策略
Caffeine提供了三种缓存驱逐策略:
基于容量:设置缓存的数量上限
// 创建缓存对象 Cache<String, String> cache = Caffeine.newBuilder() .maximumSize(1) // 设置缓存大小上限为 1 .build();
基于时间:设置缓存的有效时间
// 创建缓存对象 Cache<String, String> cache = Caffeine.newBuilder() // 设置缓存有效期为 10 秒,从最后一次写入开始计时 .expireAfterWrite(Duration.ofSeconds(10)) .build();
基于引用:设置缓存为软引用或弱引用,利用GC来回收缓存数据。性能较差,不建议使用。
// 构建cache对象 Cache<String, String> cache = Caffeine.newBuilder() .weakKeys().weakValues().build();
Caffeine.weakKeys() 使用弱引用存储key。如果没有强引用这个key,则GC时允许回收该条目
Caffeine.weakValues() 使用弱引用存储value。如果没有强引用这个value,则GC时允许回收该条目
Caffeine.softValues() 使用软引用存储value, 如果没有强引用这个value,则GC内存不足时允许回收该条目
引用类型 | 被垃圾回收时间 | 用途 | 生存时间 |
强引用 | 从来不会 | 对象的一般状态 | JVM停止运行时终止 |
软引用 | 在内存不足时 | 对象缓存 | 内存不足时终止 |
弱引用 | 在垃圾回收时 | 对象缓存 | gc运行后终止 |
虚引用 | Unknown | Unknown | Unknown |
GuavaCache和Caffeine差异
剔除算法方面,GuavaCache采用的是「LRU」算法,而Caffeine采用的是「Window TinyLFU」算法,这是两者之间最大,也是根本的区别。
立即失效方面,Guava会把立即失效 (例如:expireAfterAccess(0) and expireAfterWrite(0)) 转成设置最大Size为0。这就会导致剔除提醒的原因是SIZE而不是EXPIRED。Caffiene能正确识别这种剔除原因。
取代提醒方面,Guava只要数据被替换,不管什么原因,都会触发剔除监听器。而Caffiene在取代值和先前值的引用完全一样时不会触发监听器。
异步化方方面,Caffiene的很多工作都是交给线程池去做的(默认:ForkJoinPool.commonPool()),例如:剔除监听器,刷新机制,维护工作等。
到此这篇关于Java本地缓存Caffeine的简单使用的文章就介绍到这了,更多相关Java本地缓存Caffeine内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
最新评论