美文网首页
Guava Cache 使用

Guava Cache 使用

作者: 小道萧兮 | 来源:发表于2021-08-16 21:51 被阅读0次

缓存分为本地缓存和远端缓存。常见的远端缓存有 Redis,MongoDB;本地缓存一般使用 map 的方式保存在本地内存中。

一般在业务中操作缓存,都会操作缓存和数据源两部分。

如:put 数据时,先插入 DB,再删除原来的缓存;get 数据时,先查缓存,若未命中,则查询 DB,再将结果放入缓存中。并发时,还得兼顾本地缓存的线程安全问题。必要的时候也要考虑缓存的回收策略。

而 Guava Cache 是 Google Guava 中的一个内存缓存模块,用于将数据缓存到 JVM 内存中,很好的解决了上面提到的几个问题:

  1. 简单的 get、put 操作,能够集成数据源 ;
  2. 线程安全的缓存,与 ConcurrentMap 相似,并且增加了失效策略;
  3. 提供了三种基本的缓存回收方式:容量回收、定时回收和引用回收。其中定时回收有两种:按写入时间(最早写入的最先回收);按访问时间(最早访问的最早回收);
  4. 监控缓存加载/命中情况。

Guava Cache 存储的是键值对的集合,主要实现的缓存功能有:

  1. 自动将数据加载至缓存结构中,当缓存的数据超过最大值时,使用LRU算法替换;
  2. 具备根据节点上一次被访问或写入时间计算缓存过期机制;
  3. 还可以统计缓存使用过程中的命中率、异常率和命中率等统计数据。

一、基本使用

首先导入 maven 依赖

<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
</dependency>

下面展示了使用 Guava Cache 创建一个缓存对象并使用它,目标是缓存全班学生姓名。
其中 nameCache 的 key 是班级的 id,value 是一个 list,存储学生姓名。

import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;

public class GuavaCacheService {

    /**
     * 缓存操作对象
     */
    private final LoadingCache<String, List<String>> nameCache = loadCache(new CacheLoader<String, List<String>>() {
        @Override
        public List<String> load(String key) {
            // 从数据库加载,当key对应的value不存在时的处理逻辑
            return databaseManager.getNamesByClassId(key);
        }
    });

    /**
     * 缓存设置
     * 缓存项最大数量:10000
     * 缓存有效时间(天):1
     */
    private LoadingCache<String, List<String>> loadCache(CacheLoader<String, List<String>> cacheLoader) {
        return CacheBuilder.newBuilder()
            .concurrencyLevel(Runtime.getRuntime().availableProcessors())
            // 设置初始容量
            .initialCapacity(1000)
            // 缓存池大小
            .maximumSize(10000)
            // 设置 设定时间 后 刷新缓存
            .refreshAfterWrite(1, TimeUnit.DAYS)
            .build(cacheLoader);
    }

    /**
     * 设置缓存值
     * 若已有该key值,则会先移除(会触发removalListener移除监听器),再添加
     */
    public void put(String key, List<String> value) {
        if (StringUtils.isBlank(key) || value == null) {
            return;
        }
        try {
            nameCache.put(key, value);
        } catch (Exception e) {
            log.info("设置缓存值出错", e);
        }
    }

    /**
     * 获取缓存值
     * 如果键不存在值,将调用CacheLoader的load方法,将load方法的返回值加载到缓存
     */
    public List<String> get(String key) {
        List<String> token = null;
        try {
            token = nameCache.get(key);
        } catch (Exception e) {
            log.info("获取缓存值出错", e);
        }
        return token;
    }
}

在调用 CacheBuilder 的 build 方法时,须传递一个 CacheLoader 类型的参数,CacheLoader 的 load 方法需要我们提供实现。当调用 LoadingCache 的 get 方法时,如果不存在 key 的记录,则会自动调用 load 方法加载数据,load 方法的返回值会作为 key 对应的 value 存储到 LoadingCache中,并从 get 方法返回。

CacheBuilder 是 Guava 提供的一个快速构建缓存对象的工具类。CacheBuilder 类采用 builder 设计模式,它的每个方法都返回 CacheBuilder 本身,直到 build 方法被调用。 该类中提供了很多的参数设置选项,可以设置 cache 的默认大小,并发数,存活时间,过期策略等等。

二、配置分析

缓存的并发级别

Guava 提供了设置并发级别的 api,使得缓存支持并发的写入和读取。同 ConcurrentHashMap 类似 Guava cache 的并发也是通过分离锁实现。在一般情况下,将并发级别设置为服务器 cpu 核心数是一个比较不错的选择。

CacheBuilder.newBuilder()
        // 设置并发级别为cpu核心数
        .concurrencyLevel(Runtime.getRuntime().availableProcessors()) 
        .build();
缓存的初始容量设置

在构建缓存时,可以设置一个合理大小初始缓存容量。由于 Guava 的缓存使用了分离锁的机制,扩容的代价昂贵,所以合理的初始容量能够减少缓存容器的扩容次数。

CacheBuilder.newBuilder()
        // 设置初始容量为100
        .initialCapacity(100)
        .build();
设置最大存储

指定缓存能够存储的最大记录数量。当 Cache 中的记录数量达到最大值后,再调用 put 方法添加对象时,Guava 会先从当前缓存中删除一条,腾出空间后再将新的对象存储到 Cache 中。

  1. 基于容量的清除:通过 CacheBuilder.maximumSize() 方法设置 Cache 的最大容量数,当缓存数量达到或接近该最大值时,将清除最近最少使用的缓存;
  2. 基于权重的清除:使用 CacheBuilder.weigher() 指定一个权重函数,并且用 CacheBuilder.maximumWeight() 指定最大总重。比如每一项缓存所占据的内存空间大小都不一样,可以看作它们有不同的“权重”。
缓存清除策略
1. 基于存活时间的清除
  • expireAfterWrite 写缓存后多久过期
  • expireAfterAccess 读写缓存后多久过期
  • refreshAfterWrite 写入数据后多久过期,只阻塞当前数据加载线程,其他线程返回旧值

这几个策略时间可以单独设置,也可以组合配置。建议使用 refreshAfterWrite。

这里需要注意刷新策略和回收策略不太一样:刷新表示为 key 加载新值,这个过程可以是异步的(需要重写CacheLoader的reload方法,否则仍然是同步的调用load),而回收 key 的时候,会调用 load 方法加载值,这个过程是同步的。

相关文章

  • 高并发系统技术梳理

    缓存 缓存使用常见问题归纳Guava Cache系列之一Guava Cache系列之二Guava Cache系列之...

  • Guava Cache用法介绍

    Guava Cache的使用场景 参考1 Guava Cache用法介绍2 分布式系统缓存系列之guava cache

  • cache

    guava cache的使用

  • java之guava cache应用

    google的guava cache是一个轻量级进程内缓存框架。 如何使用guava cache a. 引入方便,...

  • Guava Cache

    原文 使用Guava cache构建本地缓存 - sameLuo的个人空间 - OSCHINA Guava Cac...

  • Guava Cache 使用

    缓存分为本地缓存和远端缓存。常见的远端缓存有 Redis,MongoDB;本地缓存一般使用 map 的方式保存在本...

  • Guava cache源码解析之构造缓存器

    guava cache使用介绍 guava cache是目前最长用的本地缓存,可以把它看成是增加了一些额外功能的C...

  • guava 本地缓存

    介绍 Guava cache是本地缓存的一种实现。 Guava Cache与ConcurrentMap很相似,但也...

  • Guava Cache本地缓存使用小结

    原创文章,转载请注明原文章地址,谢谢! Guava Cache介绍 guava cache是google guav...

  • Guava 源码分析(Cache 原理【二阶段】)

    前言 在上文「Guava 源码分析(Cache 原理)」中分析了 Guava Cache 的相关原理。 文末提到了...

网友评论

      本文标题:Guava Cache 使用

      本文链接:https://www.haomeiwen.com/subject/gljvbltx.html