【干货分享】Guava LoadingCache 使用指南:打造高性能本地缓存

本文详细介绍了 Google Guava 库中强大的本地缓存组件 ------ LoadingCache。从核心概念、创建方法到过期策略、缓存刷新等高级特性,文章通过清晰的代码示例进行了全面讲解。无论你是想解决高并发场景下的性能瓶颈,还是希望减少重复计算/IO 操作,这篇指南都能帮助你快速上手,为你的应用轻松集成一个高效、可靠的本地缓存方案。

目录

[基于Guava LoadingCache的缓存管理器](#基于Guava LoadingCache的缓存管理器)

完整实现 (GuavaCacheManager.java)

[Guava LoadingCache 核心特性](#Guava LoadingCache 核心特性)

[1. 自动加载](#1. 自动加载)

[2. 缓存配置](#2. 缓存配置)

[3. 批量操作](#3. 批量操作)

使用场景

[Guava LoadingCache 原理详解](#Guava LoadingCache 原理详解)

核心原理

工作原理示意图

核心特性解析

[1. 懒加载(Lazy Loading)](#1. 懒加载(Lazy Loading))

[2. 自动过期机制](#2. 自动过期机制)

[3. 缓存回收策略](#3. 缓存回收策略)

关键特点总结


基于Guava LoadingCache的缓存管理器

完整实现 (GuavaCacheManager.java)

java 复制代码
@Slf4j
@Component
public class CacheManager {
    @Autowired
    private TerminalInfoService terminalInfoService;
    @Autowired
    private ContainerInfoService containerInfoService;

    // 使用LoadingCache实现自动加载
    private LoadingCache<String, Object> loadingCache = CacheBuilder.newBuilder()
            // 初始容量
            .initialCapacity(100)
            // 最大容量
            .maximumSize(10000)
            // 写入后10小时过期
            .expireAfterWrite(10, TimeUnit.HOURS)
            // 访问后10小时过期
            .expireAfterAccess(10, TimeUnit.HOURS)
            // 开启统计 记录缓存统计信息
            .recordStats()
            .build(new CacheLoader<String, Object>() {
                @Override
                @Nullable
                public Object load(String key) throws Exception {
                    // 当缓存不存在时,自动调用此方法加载数据
                    log.info("自动加载缓存: {}", key);
                    return loadDataByKey(key);
                }
            });

    /**
     * 根据key获取缓存值(自动加载)
     */
    public Object getDataByKey(String key) {
        try {
            return loadingCache.get(key);
        } catch (Exception e) {
            log.error("获取缓存失败: {}", key, e);
            return null;
        }
    }

    /**
     * 根据key加载数据(CacheLoader使用)
     */
    public Object loadDataByKey(String key) throws Exception {
        if (key.startsWith(CacheConstant.TERMINAL_IMEI)) {
            return terminalInfoService.getByImei(getRealKey(key));
        } else if (key.startsWith(CacheConstant.CONTAINER_TERMINAL_ID)) {
            return containerInfoService.getByTerminalId(Long.valueOf(getRealKey(key)));
        }
        log.info("未知的key格式: " + key);
        return null;
    }

    /**
     * 分隔key标识,获取真实key
     *
     * @return
     */
    private String getRealKey(String key) {
        String[] keys = key.split(":");
        return keys[1];
    }
}

Guava LoadingCache 核心特性

1. 自动加载

java 复制代码
// 当缓存不存在时自动调用load方法
Object value = loadingCache.get("user:1");

2. 缓存配置

java 复制代码
CacheBuilder.newBuilder()
    .maximumSize(1000)                    // 最大容量
    .expireAfterWrite(30, TimeUnit.MINUTES) // 写入后过期时间
    .expireAfterAccess(10, TimeUnit.MINUTES) // 访问后过期时间
    .recordStats()                        // 开启统计
    .build(cacheLoader);

3. 批量操作

java 复制代码
// 批量获取(如果不存在会自动加载)
Map<String, Object> values = loadingCache.getAll(keys);

// 批量失效
loadingCache.invalidateAll(keys);
  1. 缓存统计
java 复制代码
CacheStats stats = loadingCache.stats();
System.out.println("命中率: " + stats.hitRate());
System.out.println("加载次数: " + stats.loadCount());

使用场景

  1. 高频访问数据:用户信息、配置信息等

  2. 计算成本高的数据:需要复杂计算或远程调用的数据

  3. 数据一致性要求不高:可以接受短暂的数据延迟

Guava LoadingCache 原理详解

核心原理

Guava LoadingCache 采用的是 "按需加载" 机制,也就是 项目启动时不自动加载全部数据,当第一次查询时才去数据库获取并缓存,过期后自动移除

工作原理示意图

XML 复制代码
+----------------+     1. get(key)       +-----------------------+
|   客户端调用    | -------------------> |   LoadingCache        |
+----------------+                       +-----------------------+
         ^                                      |
         |                                      | 2. 检查缓存是否存在
         |                                      |
         |                                      ↓
         |                            +-----------------------+
         |                            | 缓存命中?            |
         |                            +-----------------------+
         |                                      |
         |是                                    |否
         |                                      |
         |                                      ↓
         |                            +-----------------------+
         |                            | 调用CacheLoader.load()|
         |                            | 从数据源加载数据       |
         |                            +-----------------------+
         |                                      |
         |                                      | 3. 加载数据
         |                                      ↓
         |                            +-----------------------+
         |                            | 存入缓存并返回结果    |
         |                            +-----------------------+
         |                                      |
         |                                      |
         +--------------------------------------+

核心特性解析

1. 懒加载(Lazy Loading)

java 复制代码
LoadingCache<String, Object> cache = CacheBuilder.newBuilder()
    .build(new CacheLoader<String, Object>() {
        @Override
        public Object load(String key) throws Exception {
            // 只有当缓存不存在时才会调用这个方法
            System.out.println("正在加载数据: " + key);
            return database.get(key);
        }
    });

// 第一次调用 - 触发加载
Object value1 = cache.get("key1"); // 输出: "正在加载数据: key1"

// 第二次调用 - 直接从缓存获取
Object value2 = cache.get("key1"); // 无输出,直接从缓存返回

2. 自动过期机制

java 复制代码
LoadingCache<String, Object> cache = CacheBuilder.newBuilder()
    .expireAfterWrite(10, TimeUnit.MINUTES)  // 写入后10分钟过期
    .expireAfterAccess(5, TimeUnit.MINUTES)   // 最后访问后5分钟过期
    .build(cacheLoader);

// 设置后,缓存会自动管理过期和清理

3. 缓存回收策略

java 复制代码
LoadingCache<String, Object> cache = CacheBuilder.newBuilder()
    .maximumSize(1000)                    // 基于容量
    .weakKeys()                           // 使用弱引用键
    .weakValues()                         // 使用弱引用值
    .build(cacheLoader);

关键特点总结

  1. 懒加载:只有在第一次访问时才会加载数据

  2. 自动缓存:加载后的数据会自动缓存

  3. 过期自动移除:配置的过期时间到达后自动清理

  4. 线程安全:内置的线程安全机制

  5. 统计功能:提供详细的缓存命中率等统计信息

  6. 异常处理:加载失败时有相应的异常处理机制

这种设计非常适合以下场景:

  • 数据量很大,无法全部加载到内存

  • 数据访问有热点特征(部分数据被频繁访问)

  • 可以接受第一次访问的延迟

  • 数据变化不特别频繁

相关推荐
sibylyue18 天前
Guava中常用的工具类
java·guava
howeres2 个月前
Guava
guava
sqyaa.2 个月前
Guava LoadingCache
jvm·缓存·guava
杨某一辰3 个月前
【Guava】1.0.设计虚拟机的方向
guava
赶路人儿3 个月前
guava限流器RateLimiter源码详解
guava
MonkeyKing_sunyuhua3 个月前
Guava Cache 本地项目缓存
缓存·guava
杨某一辰3 个月前
【Guava】0.做自己的编程语言
c++·guava·语言设计
智_永无止境3 个月前
集合的处理:JDK和Guava孰强孰弱?
java·jdk·集合·guava
铁锚4 个月前
Guava限频器RateLimiter的使用示例
java·高并发·限流·guava·ratelimiter