聊聊GuavaCache(一)

什么是Guava Cache ?

Guava Cache 是Google提供的一种非常优秀的本地缓存解决方案,它提供了线程安全的实现机制,具有简单易用,性能好的特点,Guava Cache 不是一个单独的缓存框架,而是Guava中的一个模块

为什么我们要使用本地缓存?

  1. 相比集中式缓存(例如:Redis),速度更快,效率更高

  2. 在一定程度上,可以解决Redis的大Key问题

Guava Cache的使用场景

  1. 缓存热点数据到本地,空间换时间,提升服务的抗qps能力

  2. 缓存的数据有限,不超过内存的总量限制

  3. 允许数据有一定的延迟,即实现最终一致性

Simple Demo

接下来,我们提供一个Guava Cache构建案例:

private static LoadingCache<String, String> cache = CacheBuilder.newBuilder()
            .maximumSize(20)
            .expireAfterWrite(10, TimeUnit.SECONDS)
            .refreshAfterWrite(5, TimeUnit.SECONDS)
            .build(new CacheLoader<String, String>() {
                @Override
                public String load(String key) throws Exception {
                    log.info("数据加载, key: {}", key);
                    return key + " : result";
                }
            });
复制代码

常用参数解释

Guava Cache提供了三种缓存回收策略:

  • 容量回收:maximumSize

  • 定时回收:expireAfterAccess、expireAfterWrite

  • 引用回收:softKeys、weakKeys

核心方法介绍

load

第一次加载缓存、或者内存中不存在对应key的value时(比如value过期)这个时候会触发load方法,对于一个key,多次请求只会触发一次加载,比如有4个线程同时获取同一个key对应的value值,且value值不存在,那么这4个线程中只会有一个线程执行load方法,其他请求会被hang住,处于等待状态,所以一般我们使用本地缓存的时候,需要提前去 WarmUp,将数据load到本地缓存里,不然容易hang住其他请求。

reload

当Cache中有值,但需要重新刷新该值的时候,会触发reload方法,LoadingCache的所有更新操作,都是靠读写操作触发的,因为在其内部是没有时钟或者定时任务的,比如写操作后,超过了refresh设置的过期时间,但是之后没有cache访问,下次get的时候会触发refresh,对于同一个Key,多次请求只有一个请求触发reload,其它请求直接返回旧值,当前get的线程是同步call reload方法的,其他线程返回旧值