本地缓存 Guava Cache ,YYDS

本文详细介绍了 Guava Cache 的基础使用、过期策略、刷新策略等,包括预加载缓存、LRU 过期策略、手动刷新和自动刷新。通过实例分析了如何避免使用误区,强调了 Guava Cache 在缓存一致性、性能和稳定性上的考虑。
摘要由CSDN通过智能技术生成

前言

“缓存”一直是我们程序员聊的最多的那一类技术点,诸如 Redis、Encache、Guava Cache,你至少会听说过一个。需要承认的是,无论是面试八股文的风气,还是实际使用的频繁度,Redis 分布式缓存的确是当下最为流行的缓存技术,但同时,从我个人的项目经验来看,本地缓存也是非常常用的一个技术点。

分析 Redis 缓存的文章很多,例如 Redis 雪崩、Redis 过期机制等等,诸如此类的公众号标题不鲜出现在我朋友圈的 timeline 中,但是分析本地缓存的文章在我的映像中很少。

在最近的项目中,有一位新人同事使用了 Guava Cache 来对一个 RPC 接口的响应进行缓存,我在 review 其代码时恰好发现了一个不太合理的写法,遂有此文。

本文将会介绍 Guava Cache 的一些常用操作:基础 API 使用,过期策略,刷新策略。并且按照我的写作习惯,会附带上实际开发中的一些总结。需要事先说明的是,我没有阅读过 Guava Cache 的源码,对其的介绍仅仅是一些使用经验或者最佳实践,不会有过多深入的解析。

先简单介绍一下 Guava Cache,它是 Google 封装的基础工具包 guava 中的一个内存缓存模块,它主要提供了以下能力:

  • 封装了缓存与数据源交互的流程,使得开发更关注于业务操作

  • 提供线程安全的存取操作(可以类比 ConcurrentHashMap)

  • 提供常用的缓存过期策略,缓存刷新策略

  • 提供缓存命中率的监控

基础使用

使用一个示例介绍 Guava Cache 的基础使用方法 -- 缓存大小写转换的返回值。

private String fetchValueFromServer(String key) {
    return key.toUpperCase();
}

@Test
public void whenCacheMiss_thenFetchValueFromServer() throws ExecutionException {
    LoadingCache<String, String> cache =
        CacheBuilder.newBuilder().build(new CacheLoader<String, String>() {
            @Override
            public String load(String key) {
                return fetchValueFromServer(key);
            }
        });

    assertEquals(0, cache.size());
    assertEquals("HELLO", cache.getUnchecked("hello"));
    assertEquals("HELLO", cache.get("hello"));
    assertEquals(1, cache.size());
}

使用 Guava Cache 的好处已经跃然于纸上了,它解耦了缓存存取与业务操作。CacheLoader 的 load 方法可以理解为从数据源加载原始数据的入口,当调用 LoadingCache 的 getUnchecked 或者 get方法时,Guava Cache 行为如下:

  • 缓存未命中时,同步调用 load 接口,加载进缓存,返回缓存值

  • 缓存命中,直接返回缓存值

  • 多线程缓存未命中时,A 线程 load 时,会阻塞 B 线程的请求,直到缓存加载完毕

注意到,Guava 提供了两个 getUnchecked 或者 get 加载方法,没有太大的区别,无论使用哪一个,都需要注意,数据源无论是 RPC 接口的返回值还是数据库,都要考虑访问超时或者失败的情况,做好异常处理。

预加载缓存

预加载缓存的常见使用场景:

  • 老生常谈的秒杀场景,事先缓存预热,将热点商品加入缓存;

  • 系统重启过后,事先加载好缓存,避免真实请求击穿缓存

Guava Cache 提供了 put 和 putAll 方法

@Test
public void whenPreloadCache_thenPut() {
    LoadingCache<String, String> cache =
        CacheBuilder.newBuilder().build(new CacheLoader<String, String>() {
            @Override
            public String load(Stri
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值