简单高效的缓存解决方案--Guava Cache

news/2025/11/18 11:30:15/文章来源:https://www.cnblogs.com/hellodeyang/p/19236591

目录
  • 简单高效的缓存解决方案--Guava Cache
    • 什么是 Guava Cache?
    • 核心优势
      • 1. 自动驱逐策略
      • 2. 时间-based 过期
      • 3. 自动加载数据
    • 实战示例
      • 1. 配置缓存实例
      • 2. 批量操作
      • 3. 缓存统计与监控
    • 高级特性
      • 1. 缓存刷新
      • 2. 移除监听器
      • 3. 异步刷新
    • 最佳实践
      • 1. 合理设置缓存大小
      • 2. 处理加载异常
      • 3. 结合 Spring 使用
    • 性能考虑
      • 1. 选择合适的驱逐策略
      • 2. 监控与调优
    • 总结

简单高效的缓存解决方案--Guava Cache

在构建高性能Java应用时,缓存是提升系统性能的关键技术之一。虽然 ConcurrentHashMap 能够提供基础的键值存储,但在实际的缓存场景中,我们往往需要更多专业特性。这就是 com.google.common.cache 大显身手的地方。

什么是 Guava Cache?

Guava Cache 是 Google Guava 库中的一个本地缓存实现,它提供了比普通 Map 更丰富的缓存特性,包括自动驱逐、过期策略、统计信息等,专门为缓存场景深度优化。

Guava Cache 是超越普通Map的高性能本地缓存。

从本质上讲,它确实就是一个 Map

但更准确地说,它是一个「智能的、自带管理功能的 Map」

<dependencies><!-- Guava 核心依赖 --><dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><version>32.1.3-jre</version><!-- 或者使用 Android 版本 --><!-- <version>32.1.3-android</version> --></dependency>
</dependencies>

核心优势

1. 自动驱逐策略

普通 Map 需要手动管理内存,而 Guava Cache 提供了多种自动驱逐机制:

// 基于大小的驱逐
Cache<String, Object> sizeBasedCache = CacheBuilder.newBuilder().maximumSize(1000) // 最多1000个条目.build();// 基于权重的驱逐
Cache<String, Object> weightBasedCache = CacheBuilder.newBuilder().maximumWeight(1000000) // 总权重最大100万.weigher((String key, Object value) -> getWeight(value)).build();

2. 时间-based 过期

Cache<String, Object> timeBasedCache = CacheBuilder.newBuilder().expireAfterWrite(10, TimeUnit.MINUTES)  // 写入后10分钟过期.expireAfterAccess(5, TimeUnit.MINUTES)  // 5分钟未被访问则过期.build();

3. 自动加载数据

最强大的特性之一:当缓存未命中时自动加载数据。

LoadingCache<String, User> userCache = CacheBuilder.newBuilder().maximumSize(1000).build(new CacheLoader<String, User>() {@Overridepublic User load(String userId) throws Exception {// 当缓存不存在时,自动调用此方法加载数据return userService.getUserById(userId);}});// 使用 - 如果不存在会自动加载
User user = userCache.get("123");

实战示例

1. 配置缓存实例

public class ProductCache {private final LoadingCache<String, Product> cache;public ProductCache(ProductService productService) {this.cache = CacheBuilder.newBuilder().maximumSize(500).expireAfterWrite(30, TimeUnit.MINUTES).refreshAfterWrite(10, TimeUnit.MINUTES) // 定时刷新.recordStats() // 开启统计.build(new CacheLoader<String, Product>() {@Overridepublic Product load(String productId) {return productService.getProduct(productId);}@Overridepublic ListenableFuture<Product> reload(String key, Product oldValue) {// 异步刷新return productService.getProductAsync(key);}});}public Product getProduct(String productId) {try {return cache.get(productId);} catch (ExecutionException e) {throw new RuntimeException("Failed to load product: " + productId, e);}}
}

2. 批量操作

// 批量获取
Map<String, User> users = userCache.getAll(Arrays.asList("1", "2", "3"));// 批量失效
cache.invalidateAll(Arrays.asList("key1", "key2"));// 清空缓存
cache.invalidateAll();

3. 缓存统计与监控

CacheStats stats = cache.stats();logger.info("缓存命中率: {}%", stats.hitRate() * 100);
logger.info("平均加载时间: {}ms", stats.averageLoadPenalty() / 1000000);
logger.info("缓存命中次数: {}", stats.hitCount());
logger.info("缓存未命中次数: {}", stats.missCount());
logger.info("驱逐次数: {}", stats.evictionCount());

高级特性

1. 缓存刷新

LoadingCache<String, Config> configCache = CacheBuilder.newBuilder().refreshAfterWrite(1, TimeUnit.MINUTES) // 1分钟后刷新.build(new CacheLoader<String, Config>() {@Overridepublic Config load(String key) {return loadConfig(key);}});

2. 移除监听器

Cache<String, Data> cache = CacheBuilder.newBuilder().removalListener((RemovalNotification<String, Data> notification) -> {RemovalCause cause = notification.getCause();String key = notification.getKey();Data value = notification.getValue();logger.info("Key {} 被移除,原因: {}", key, cause);if (cause == RemovalCause.SIZE) {// 处理因大小限制被移除的情况metrics.recordEviction();}}).build();

3. 异步刷新

LoadingCache<String, HeavyObject> asyncCache = CacheBuilder.newBuilder().refreshAfterWrite(10, TimeUnit.MINUTES).build(CacheLoader.asyncReloading(new CacheLoader<String, HeavyObject>() {@Overridepublic HeavyObject load(String key) {return computeHeavyObject(key);}}, executorService // 使用线程池异步刷新));

最佳实践

1. 合理设置缓存大小

// 根据应用内存情况设置合理的大小
CacheBuilder.newBuilder().maximumSize(calculateOptimalSize()) // 动态计算.build();

2. 处理加载异常

LoadingCache<String, Data> safeCache = CacheBuilder.newBuilder().build(new CacheLoader<String, Data>() {@Overridepublic Data load(String key) throws Exception {try {return externalService.getData(key);} catch (Exception e) {// 返回默认值或抛出特定异常return getDefaultData();}}});

3. 结合 Spring 使用

@Component
public class CacheManager {@Autowiredprivate UserRepository userRepository;private LoadingCache<Long, User> userCache;@PostConstructpublic void init() {userCache = CacheBuilder.newBuilder().maximumSize(1000).expireAfterAccess(2, TimeUnit.HOURS).recordStats().build(CacheLoader.from(userRepository::findById));}public User getUser(Long id) {try {return userCache.get(id);} catch (ExecutionException e) {throw new RuntimeException("Cache load failed", e);}}
}

性能考虑

1. 选择合适的驱逐策略

  • maximumSize(): 适用于条目大小相近的场景
  • maximumWeight(): 适用于条目大小差异较大的场景
  • expireAfterWrite(): 适用于数据不经常变化的场景
  • expireAfterAccess(): 适用于需要保留热门数据的场景

2. 监控与调优

// 定期输出缓存统计
scheduledExecutorService.scheduleAtFixedRate(() -> {CacheStats stats = cache.stats();if (stats.requestCount() > 0) {logger.info("缓存统计: 命中率={}%, 加载次数={}, 平均加载时间={}ms",String.format("%.2f", stats.hitRate() * 100),stats.loadCount(),String.format("%.2f", stats.averageLoadPenalty() / 1000000.0));}
}, 1, 1, TimeUnit.MINUTES);

总结

Guava Cache 提供了一个功能完整、性能优异的本地缓存解决方案。与普通 Map 相比,它在以下方面表现出色:

  • 自动内存管理 - 无需手动清理
  • 灵活的过期策略 - 时间和访问频率控制
  • 丰富的统计信息 - 便于监控和调优
  • 线程安全 - 内置并发控制
  • 自动加载 - 简化缓存未命中处理

对于大多数Java应用的本地缓存需求,Guava Cache 都是一个值得信赖的选择。它既保持了使用的简洁性,又提供了企业级缓存所需的强大功能。

适用场景:数据量不大、访问频繁、计算成本高的数据缓存,如配置信息、用户会话、数据库查询结果等。

不适用场景:分布式环境、超大容量缓存(考虑 Redis 等分布式缓存)。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/968769.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2025年柱状活性炭实力厂家权威推荐榜单:中水回用活性炭/压块破碎活性炭/活性炭源头厂家精选

在环保政策持续加码的背景下,柱状活性炭作为水处理、空气净化等领域的核心吸附材料,其品质与供应商的技术实力日益成为市场关注的焦点。 据行业数据显示,2025年全球柱状活性炭市场规模预计将达到亿元级别,其中压块…

基于Dify工作流与Jira API构建自优化测试系统

关注 霍格沃兹测试学院公众号,回复「资料」, 领取人工智能测试开发技术合集 将测试智能体与Jira集成,可以构建一个能够自动识别问题、执行测试并反馈结果的智能化质量保障体系。这种集成不仅能将测试活动直接嵌入开发…

2025 年 10 月科技前沿全景:从量子跃迁到生命重构的文明拐点 - 实践

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

传统化工企业的 “能耗死循环”:MyEMS 如何用 “数据中台” 打通设备孤岛?

在 “双碳” 目标与能源成本高企的双重压力下,传统化工企业正面临一场严峻的 “能耗困局”。作为典型的高耗能行业,化工生产流程长、设备种类多、能源消耗量大,许多企业陷入了一个难以突破的 “能耗死循环”—— 设…

2025年苗木批发基地实力批发商排行榜全新发布,丝棉木/红叶石楠/苗木/红叶李/国槐/青叶复叶槭/紫薇/油松/白蜡/金叶女贞/栾树种植哪家好

苗木批发行业迎来新一轮发展机遇 随着城镇化进程加快和生态文明建设不断推进,苗木批发行业正迎来新一轮发展机遇。据行业数据显示,2024年全国苗木需求量同比增长12%,市场规模突破千亿元。在此背景下,专业苗木批发基…

2025年11月国内矿山设备检测检验公司权威推荐榜单:专业选择指南

摘要 随着矿山安全法规的日趋严格和行业标准的不断提升,2025年矿山设备检测检验行业迎来了快速发展期。本文基于市场调研和行业数据分析,为您推荐五家国内领先的矿山设备检测检验公司,并提供详细比较和选择指南,帮…

2025年国内矿山设备检测检验公司十大权威推荐榜单

摘要 随着矿山安全生产要求的不断提高,矿山设备检测检验行业在2025年迎来快速发展期。本文基于行业数据和技术标准,为您推荐国内十大矿山设备检测检验公司,并提供详细的服务对比表单供参考选择。 排名榜单 第一名:…

2025留学机构哪家比较好一点

2025留学机构哪家比较好一点一、2025年留学机构怎么选?五大疑问帮你理清思路作为一位从事国际教育规划工作超过15年的资深顾问,我每天都会收到大量关于留学机构选择的咨询。2025年已经过去大半,不少准备留学的同学和…

2025杭州最大留学中介机构在哪里

2025杭州最大留学中介机构在哪里一、杭州留学中介如何选?五大疑问帮你理清思路作为从事国际教育规划工作已满十年的专业人士,我每天都会接触到大量杭州地区学生和家长的咨询。在2025年10月25日的今天,随着留学市场的…

2025出国留学机构排名对比图

2025出国留学机构排名对比图一、留学中介选择难题:你也在纠结吗?作为从事10年国际教育规划师的我,经常收到学生和家长的咨询:出国留学机构哪家更靠谱?面对市面上众多的选择,许多人在搜索引擎上反复查询类似问题,…

2025成都留学中介推荐

2025成都留学中介推荐一、成都留学中介怎么选?这些疑问你有吗?作为从事10年国际教育规划师,我经常遇到成都学生和家长咨询留学中介选择问题。在2025年10月24日的今天,留学市场更加多元,但疑问依旧集中:成都留学中…

2025年本地人推荐口碑好的火锅哪家好吃,社区火锅/烧菜火锅/老火锅/火锅店/美食/火锅/特色美食回头客多的推荐

成都火锅市场深度解析 作为川渝美食文化的代表,成都火锅市场近年来呈现出多元化发展趋势。据最新餐饮行业数据显示,成都火锅门店数量已突破8000家,年消费人次超过1.2亿。在激烈的市场竞争中,一批注重传统工艺与创新…

JSAPIThree之Bloom 效果学习笔记:让我的 3D 场景发光发亮!

这是一篇关于 Bloom(泛光)效果的学习笔记,以初学者的视角记录从零开始学习如何在 mapvthree 中实现 Bloom 效果的过程,包含详细的实践步骤和踩坑经验。作为一个刚开始学习 mapvthree 的小白,今天我要学习一个超酷…

查看当前 Java 运行的版本?

查看当前 Java 运行的版本?要查看当前运行的 Java 版本,可以通过以下方法:命令行 / 终端方式(最常用):打开命令提示符(Windows)或终端(Mac/Linux) 输入命令:java -version 回车后,会显示类似如下信息(包含…

webman是异步非阻塞的,这个是指在处理接口请求的时候么,那如果接口程序中,有外部的请求或者读写数据库即IO开销,那这个是异步非阻塞的么 goframe又是怎样的

非常好的问题!你已经触及了现代 Web 框架中一个非常关键但容易混淆的点:“框架是异步非阻塞的” ≠ “你的业务代码自动变成异步非阻塞”。我们来分别分析 Webman(PHP) 和 GoFrame(Go) 的行为,尤其是当你在接口…

浅显易懂的解释一下RRF加权算法的意思

想象一下,你想找一部“最好看的科幻电影”。你没法自己看完所有电影,于是你问了三位你非常信任的朋友(我们叫他们小A、小B、小C),让他们每人给你一个前5名的推荐名单。 现在你拿到了三个不同的名单:小A的名单 (偏…

RabbitMQ 在 Windows 下频繁出现 “vhost / is down” 与 Mnesia 损坏问题的完整排查与解决方案

最近在一个项目中,我遇到了一个非常棘手且重复出现的 RabbitMQ 问题: 程序重启后 RabbitMQ 无法正常连接,所有通道都无法建立,并报错 vhost / is down。 RabbitMQ 管理界面连接数为 0,服务明明在运行,但应用无法…

实用指南:用 FPGA 实现 PCIe 传输,开源核 LitePCIe 深度解读

实用指南:用 FPGA 实现 PCIe 传输,开源核 LitePCIe 深度解读2025-11-18 11:12 tlnshuju 阅读(0) 评论(0) 收藏 举报pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !impor…

2025年东莞大小泥水工程公司权威推荐榜单:洁净房设计/修缮工程/钢构工程施工源头公司精选

在东莞制造业升级的浪潮中,一批在泥水工程领域兼具专业技术与实战经验的装饰公司,正成为提升工业空间品质与效能的关键力量。 工业厂房与生产空间的效能,很大程度上取决于基础工程的品质。泥水工程作为厂房装修的基…

vue3 创建简单路由的简单笔记

vue3 创建简单路由的简单笔记 导入和配置路由 import { createRouter, createWebHistory, type Router, type RouterOptions } from vue-router import MainPage from ../../pages/main/MainPage.vue import AboutPage…