1.简介

Guava Cache 是一套完善的本地缓存机制(JVM缓存——堆缓存,创建一些全局容器,比如 list。set,map 等 来做数据存储,缺点:并发能力差,没有淘汰策略,缓存过期,加载需要手动处理,并发处理能力差等)。类似的 有  currentHashMap,EhChached

2.应用场景

对性能有非常高需求,数据变化不大,占用内存不大,有访问整个集合的需求,数据允许不一致。

Guava Cache

currentHashmap

Ehcached

高并发,不需要持久化

高并发

持久化,二级缓存

3.的优势

缓存过期和淘汰机制

在GuavaCache中可以设置Key的过期时间,包括访问过期和创建过期 GuavaCache在缓存容量达到指定大小时,采用LRU的方式,将不常使用的键值从Cache中删除

并发处理能力

GuavaCache类似CurrentHashMap,是线程安全的。 提供了设置并发级别的api,使得缓存支持并发的写入和读取 采用分离锁机制,分离锁能够减小锁力度,提升并发能力 分离锁是分拆锁定,把一个集合看分成若干partition, 每个partiton一把锁。ConcurrentHashMap就是分了16个区域,这16个区域之间是可以并发的。GuavaCache采用Segment做分区。

更新锁定

一般情况下,在缓存中查询某个key,如果不存在,则查源数据,并回填缓存。(Cache Aside Pattern)在高并发下会出现,多次查源并重复回填缓存,可能会造成源的宕机(DB),性能下降GuavaCache可以在CacheLoader的load方法中加以控制,对同一个key,只让一个请求去读源并回填缓存,其他请求阻塞等待。

集成数据源

一般我们在业务中操作缓存,都会操作缓存和数据源两部分 而GuavaCache的get可以集成数据源,在从缓存中读取不到时可以从数据源中读取数据并回填缓存监控缓存加载/命中情况统计

4.使用

4.1 pom

com.google.guava
guava
28.2-jre
4.2 创建方式
CacheLoader 和 Callable callback
CacheLoader :在创建 cache 对象时,采用 CacheLoader 来获取数据,当缓存不存在时能够自动加载数据到缓存中。
Cache cache = CacheBuilder.newBuilder()
//设置cache的初始大小为3,要合理设置该值,清除策略 LRU+FIFO
.initialCapacity(3)
//key 最大数量
.maximumSize(10)
//置并发数为 cpu核数 ,即同一时间最多只能有 cpu核数 个线程往cache执行写入操作
.concurrencyLevel(Runtime.getRuntime().availableProcessors())
//统计命中率
.recordStats()
//设置cache中的数据在写入之后的存活时间为10秒
.expireAfterWrite(10, TimeUnit.SECONDS)
//设置cache中的数据在访问之后的存活时间为10秒——可以筛选 热数据
.expireAfterAccess(10, TimeUnit.SECONDS)
//设置cache中的数据在写入之后的下次刷新时间为10秒
.refreshAfterWrite(10, TimeUnit.SECONDS)
//清除弱值引用——对象重新定义,索引失效
//weakKeys,weakValues,softValues三种方式都是应用java的弱引用(WeakReference)和软引用(SoftReference)在内存不足时会自动触发gc,被回收。
.weakKeys()
.weakValues()
.softValues()
//添加移除监视器
.removalListener(new RemovalListener() {
@Override
public void onRemoval(
RemovalNotification removalNotification) {
//移除的key 移除的原因
System.out.println(removalNotification.getKey()
+":"+removalNotification.getCause());
}
})
//构建cache实例
.build(new CacheLoader() {
//读取数据源
@Override
public Object load(String key) throws Exception {
// key 所处的数据源 get 时 自动加载--将value替换为业务程序
return value;
}
});
Callable callback
cache.get(key, new Callable(){
//回调方法用于读源并写入缓存
@Override
public Object call() throws Exception {
//读源--获取key的值
Object value=value;
//写回缓存-可不写会自动写入
//cache.put(key,value);
return value;
}
});
4.3 常用方法
/**
* 通过key获取缓存中的value,若不存在直接返回null
*/
V getIfPresent(Object key);
/**
* 通过key获取缓存中的value,若不存在就通过valueLoader来加载该value
* 整个过程为 "if cached, return; otherwise create, cache and return"
* 注意valueLoader要么返回非null值,要么抛出异常,绝对不能返回null
*/
V get(K key, Callable extends V> valueLoader) throws ExecutionException;
/**
* 添加缓存,若key存在,就覆盖旧值
*/
void put(K key, V value);
/**
* 删除该key关联的缓存
*/
void invalidate(Object key);
/**
* 删除所有缓存
*/
void invalidateAll();
/**
* 执行一些维护操作,包括清理缓存
*/
void cleanUp();
4.4 缓存数据删除
GuavaCache的数据删除分为:被动删除和主动删除
被动删除
// 基于数据大小的删除:删除规则:LRU+FIFO 访问次数一样少的情况下,FIFO
maximumSize() :
// 基于过期时间删除
expireAfterWrite()
expireAfterAccess()
//基于引用的删除-可以通过weakKeys和weakValues方法指定Cache只保存对缓存记录key和value的弱引用。这样当没有其他强引用指向key和value时,key和value对象就会被垃圾回收器回收。
weakKeys()
weakValues()
softValues()
主动删除
//单独删除
cache.invalidate("1");
//批量删除
cache.invalidateAll(Arrays.asList("1","2"));
//清空所有数据
cache.invalidateAll();