Guava Cache使用
介绍
Guava是Google提供的一套Java工具包,而Guava Cache是一套非常完善的本地缓存机制(JVM缓
存)。
Guava cache的设计来源于CurrentHashMap,可以按照多种策略来清理存储在其中的缓存值且保持很高的并发读写性能。
应用场景
本地缓存的应用场景:
- 对性能有非常高的要求
- 不经常变化
- 占用内存不大
- 有访问整个集合的需求
- 数据允许不时时一致
Guava Cache 的优势:
- 缓存过期和淘汰机制
在GuavaCache中可以设置Key的过期时间,包括访问过期和创建过期
GuavaCache在缓存容量达到指定大小时,采用LRU的方式,将不常使用的键值从Cache中删除
- 并发处理能力
GuavaCache类似CurrentHashMap,是线程安全的。提供了设置并发级别的api,使得缓存支持并发的写入和读取
采用分离锁机制,分离锁能够减小锁力度,提升并发能力分离锁是分拆锁定,把一个集合看分成若干partition, 每个partiton一把锁。ConcurrentHashMap就是分了16个区域,这16个区域之间是可以并发的。GuavaCache采用Segment做分区。
- 更新锁定
一般情况下,在缓存中查询某个key,如果不存在,则查源数据,并回填缓存。(Cache AsidePattern)
在高并发下会出现,多次查源并重复回填缓存,可能会造成源的宕机(DB),性能下降
GuavaCache可以在CacheLoader的load方法中加以控制,对同一个key,只让一个请求去读源并
回填缓存,其他请求阻塞等待。
- 集成数据源
一般我们在业务中操作缓存,都会操作缓存和数据源两部分而GuavaCache的get可以集成数据源,在从缓存中读取不到时可以从数据源中读取数据并回填缓存
- 监控缓存加载/命中情况
统计
Guava Cache创建方式
CacheLoader和Callable callback
CacheLoader 创建
// 1 CacheLoader 方式创建
LoadingCache<String, Object> cache = CacheBuilder.newBuilder().maximumSize(7).build(new CacheLoader<String, Object>() {
//读数据源 加载数据到缓存
@Override
public String load(String s) throws Exception {
return hm.get(s) + "";
}
});
Callable 方式创建
//2 Callable 方式创建
public static Object get(String key, LoadingCache<String, Object> cache) throws Exception {
//get key的时候 缓存中没有则会回调 Callable 可以回写数据源到缓存中
Object value = cache.get(key, new Callable() {
@Override
public Object call() throws Exception {
Object v = hm.get(key);
//设置回缓存 不写也可以
//cache.put(key,v);
return v;
}
});
return value;
}
初始化往缓存里添加数据
cache使用 get方法获取Key的时候 如果没有则会调用load方法
public static void initCache(LoadingCache cache) throws Exception {
/* 前三条记录 */
for (int i = 1; i <= 3; i++) {
//get时候没数据 会 load装配进去 相当一个连接数据源,如果缓存没有 则读取数据源,加载load方法
cache.get(String.valueOf(i));
}
}
打印缓存中所有的数据
public static void displayCache(LoadingCache cache) throws Exception {
Iterator its = cache.asMap().entrySet().iterator();
while (its.hasNext()) {
System.out.println(its.next().toString());
}
}
测试
//默认数据源
static Map<String,Integer> hm = new HashMap<>();
static {
hm.put("1",11);
hm.put("2",22);
hm.put("3",33);
hm.put("4",44);
hm.put("5",55);
hm.put("6",66);
}
/* 初始化cache */
initCache(cache);
//获取缓存数量
System.out.println(cache.size());
displayCache(cache);
System.out.println("=============================");
读取缓存中的1的数据 缓存没有就返回Null
System.out.println(cache.getIfPresent("1"));
// CacheLoader 在创建cache对象时,采用CacheLoader来获取数据,当缓存不存在时能够自动加载数据到缓存中。
System.out.println("=============================");
get(4+"",cache);
//打印添加4之后的所有缓存
displayCache(cache);
可以看到,刚开始初始化是三条数据。其中获取key是1 的数据,然后获取key是4 加载4的值到缓存中,最后打印出所有的缓存数据。