Guava缓存高级实战

629 阅读2分钟

截屏2022-04-29 上午9.27.44.png

1:什么是Guava

Guava是谷歌提供的一套Java工具包,而Guava Cache是一套非常完善的本地缓存机制(JVM缓存。Guava cache的设计来源于CurrentHashMap,可以按照多种策略来清理存储在其中的缓存值且保持很高的并发读写性能。

2:Guava应用场景(用作本地缓存)

  • 对性能有非常高的要求
  • 不经常变化
  • 对内存占用率不高
  • 数据允许不时时一致

3:Guava的二种创建方式-CacheLoader

//模拟数据源
final class Constants{

    public static Map<String,Object> hm = new HashMap<>();

    static {
        hm.put("1","张飞");
        hm.put("2","关羽");
        hm.put("3","赵云");
        hm.put("4","刘备");
        hm.put("5","黄忠");
    }
}

//CacheLoader的方式创建
LoadingCache<String,Object> cache = CacheBuilder.newBuilder().build(new CacheLoader<String, Object>() {
    //读取数据源
    @Override
    public Object load(String s) throws Exception {
        //这里模拟从数据库读取数据
        return Constants.hm.get(s);
    }
});

//从缓存中获取数据,如果缓存没有就会从数据库中读取
String result = cache.get("1");

//打印当前缓存的所有记录
ConcurrentMap<String, Object> concurrentMap = cache.asMap();
for(String key : concurrentMap.keySet()) {
      System.out.println(key + " : " + concurrentMap.get(key));
}

4:Guava的二种创建方式-Callable callback

Cache<Object, Object> cache = CacheBuilder.newBuilder().build();

//获取缓存,如果缓存没有通过Callable去数据库获取缓存
String value = (String)cache1.get("1",new Callable<String>() {
    @Override
    public String call() throws Exception {
        //读取数据源
        String value = (String)Constants.hm.get("1");
        //将数据写到缓存中
        cache.put("1",value);
        return value;
    }
});

//打印当前缓存的所有记录
ConcurrentMap<String, Object> concurrentMap = cache.asMap();
for(String key : concurrentMap.keySet()) {
      System.out.println(key + " : " + concurrentMap.get(key));
}

5:Guava的数据删除-被动删除

5.1:基于数据大小删除

LoadingCache<String,Object> cache = CacheBuilder.newBuilder()
  //缓存中最多存在的数量,类似一个集合最大的容量是3一样,如果大于3个就会删除一个缓存 LRU+FIFO的规则去删除缓存
  .maximumSize(3) 
  .build(new CacheLoader<String, Object>() {
    //读取数据源
    @Override
    public Object load(String s) throws Exception {
        //这里模拟从数据库读取数据
        return Constants.hm.get(s);
    }
});

5.2:基于过期时间删除

LoadingCache<String,Object> cache = CacheBuilder.newBuilder()
   //这个key在写入3秒后就会被删除,不管期间有没有被访问
  .expireAfterWrite(3, TimeUnit.SECONDS) 
  
  //这个key在3秒内没有访问就被删除
  .expireAfterAccess(3,TimeUnit.SECONDS) 
  
  .build(new CacheLoader<String, Object>() {
    //读取数据源
    @Override
    public Object load(String s) throws Exception {
        //这里模拟从数据库读取数据
        return Constants.hm.get(s);
    }
});

5.3:基于引用的删除

可以通过weakKeys和weakValues方法指定Cache只保存对缓存记录key和value的弱引用。这样当没有其他强引用指向key和value时,key和value对象就会被垃圾回收器回收。

LoadingCache<String,Object> cache = CacheBuilder.newBuilder()
  //key的弱引用
  .weakKeys()
  //value的弱引用
  .weakValues()
  .build(new CacheLoader<String, Object>() {
    //读取数据源
    @Override
    public Object load(String s) throws Exception {
        //这里模拟从数据库读取数据
        return Constants.hm.get(s);
    }
});

6:Guava的数据删除-主动删除

6.1:单个删除

//单独删除 删除key=1的缓存
cache.invalidate("1");

6.2:批量删除

//批量删除 删除key = 1和2的缓存
cache.invalidateAll(Arrays.asList(1,2));

6.3:清空所有数据

//清空所有数据
cache.invalidateAll();

7:Guava的缓存命中率

LoadingCache<String,Object> cache = CacheBuilder.newBuilder()
  //是一个记录,统计缓存命中率
  .recordStats()  
  .build(new CacheLoader<String, Object>() {
    //读取数据源
    @Override
    public Object load(String s) throws Exception {
        //这里模拟从数据库读取数据
        return Constants.hm.get(s);
    }
});

//查看缓存命中率
CacheStats stats = cache.stats();