【干货分享】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. 异常处理:加载失败时有相应的异常处理机制

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

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

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

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

  • 数据变化不特别频繁

相关推荐
谢亮_vipxieliang4 天前
ValidX vs Google Guava Preconditions:验证 vs 断言
java·spring boot·后端·spring cloud·hibernate·guava
吴声子夜歌7 天前
Guava——散列
java·guava
吴声子夜歌7 天前
Guava——并发(二)
java·网络·guava
吴声子夜歌7 天前
Guava——事件总线
java·网络·guava
吴声子夜歌7 天前
Guava——并发(一)
java·guava
吴声子夜歌7 天前
Guava——反射
java·开发语言·guava
吴声子夜歌8 天前
Guava——基本工具(二)
windows·python·guava
吴声子夜歌8 天前
Guava——基本工具(一)
windows·guava
吴声子夜歌8 天前
Guava——集合(二)
java·guava
吴声子夜歌8 天前
Guava——缓存
缓存·guava