Spring Boot中集成Guava Cache或者Caffeine

一、在Spring Boot(1.x版本)中集成Guava Cache

  • 注意: Spring Boot 2.x+用户:优先使用Caffeine,性能更优且维护活跃。

1. 添加依赖

pom.xml中添加Guava依赖:

<dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><version>31.0.1-jre</version> <!-- 使用最新版本 -->
</dependency>

2. 启用缓存支持

在启动类上添加@EnableCaching注解:

@SpringBootApplication
@EnableCaching
public class Application {public static void main(String[] args) {SpringApplication.run(Application.class, args);}
}

3. 配置Guava缓存管理器

创建配置类定义CacheManager Bean:

@Configuration
public class CacheConfig {@Beanpublic CacheManager cacheManager() {GuavaCacheManager cacheManager = new GuavaCacheManager();cacheManager.setCacheBuilder(CacheBuilder.newBuilder().expireAfterWrite(10, TimeUnit.MINUTES) // 写入10分钟后过期.maximumSize(100) // 最大缓存数量.recordStats()); // 开启统计信息return cacheManager;}
}

4. 使用缓存注解

在Service层使用@Cacheable@CacheEvict等注解:

@Service
public class UserService {// 缓存查询结果,key为id@Cacheable(value = "USER_CACHE", key = "#id")public User getUserById(Long id) {return userRepository.findById(id).orElse(null);}// 更新缓存@CachePut(value = "USER_CACHE", key = "#user.id")public User updateUser(User user) {return userRepository.save(user);}// 删除缓存@CacheEvict(value = "USER_CACHE", key = "#id")public void deleteUser(Long id) {// 删除用户逻辑userRepository.deleteById(id);}}

5. 验证缓存效果

编写测试类或调用接口验证缓存是否生效:

@SpringBootTest
public class UserServiceTest {@Autowiredprivate UserService userService;@Testpublic void testCache() {// 第一次调用,执行方法User user1 = userService.getUserById("123");// 第二次调用,从缓存获取User user2 = userService.getUserById("123");// 验证是否为同一对象(缓存生效)assertThat(user1).isSameAs(user2);}
}

高级配置

  • 多缓存配置:为不同缓存设置不同策略:

    @Bean
    public CacheManager cacheManager() {GuavaCacheManager cacheManager = new GuavaCacheManager();cacheManager.setCacheBuilder(CacheBuilder.newBuilder().expireAfterWrite(30, TimeUnit.MINUTES).maximumSize(500));cacheManager.setCacheBuilder("userCache", CacheBuilder.newBuilder().expireAfterWrite(10, TimeUnit.MINUTES).maximumSize(100));return cacheManager;
    }
    
  • 刷新策略:使用refreshAfterWrite定时刷新(需配合LoadingCache):

    CacheBuilder.newBuilder().refreshAfterWrite(5, TimeUnit.MINUTES).build(CacheLoader.from(key -> loadData(key)));
    
  • 统计信息:通过recordStats()启用统计,使用cache.getStatistics()获取命中率等信息。

常见问题

  1. 缓存未生效

    • 确保启动类有@EnableCaching
    • 检查方法是否为public(注解在私有方法上无效)。
  2. 配置未应用

    • 确认CacheManager Bean正确注册。
    • 检查缓存名称是否匹配@Cacheable(value = "cacheName")
  3. 内存溢出

    • 合理设置maximumSizeexpireAfterAccess/Write

通过以上步骤,即可在Spring Boot中高效使用Guava Cache实现本地缓存,提升应用性能。



二、Spring Boot 2.x及以上版本(推荐使用Caffeine)

在Spring Boot 2.x及以上版本中,Caffeine作为默认的本地缓存组件,取代了Guava Cache,提供了更高的性能和更灵活的配置。


1. 添加依赖

需引入spring-boot-starter-cachecaffeine依赖:

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency><groupId>com.github.ben-manes.caffeine</groupId><artifactId>caffeine</artifactId><version>3.1.8</version> <!-- 推荐使用最新版本 -->
</dependency>

2. 启用缓存支持

在启动类添加@EnableCaching注解:

@SpringBootApplication
@EnableCaching
public class Application {public static void main(String[] args) {SpringApplication.run(Application.class, args);}
}

3. 配置Caffeine缓存

方式一:通过配置文件

application.yml中定义全局缓存参数:

spring:cache:type: caffeinecaffeine:spec: maximumSize=500,expireAfterWrite=600s,initialCapacity=100cache-names: userCache, productCache  # 定义缓存名称
  • 常用参数
    • maximumSize:最大缓存条目数
    • expireAfterWrite:写入后过期时间
    • initialCapacity:初始容量。
方式二:通过Java Config类

为不同缓存设置独立策略(推荐多缓存场景):

@Configuration
@EnableCaching
public class CacheConfig {public enum Caches {USER_CACHE(600, 1000),  // 有效期600秒,最大容量1000PRODUCT_CACHE(3600);private final int ttl;private final int maxSize;Caches(int ttl, int maxSize) {this.ttl = ttl;this.maxSize = maxSize;}public int getTtl() {return ttl;}public int getMaxSize() {return maxSize;}}@Beanpublic CacheManager cacheManager() {SimpleCacheManager manager = new SimpleCacheManager();List<CaffeineCache> caches = Arrays.stream(Caches.values()).map(c -> new CaffeineCache(c.name(), Caffeine.newBuilder().expireAfterWrite(c.getTtl(), TimeUnit.SECONDS).maximumSize(c.getMaxSize()).build())).collect(Collectors.toList());manager.setCaches(caches);return manager;}
}

此方式支持为每个缓存单独配置过期时间和容量。


4. 使用缓存注解

在Service层通过注解操作缓存:

@Service
public class UserService {// 缓存查询结果,key为id@Cacheable(value = "USER_CACHE", key = "#id")public User getUserById(Long id) {return userRepository.findById(id).orElse(null);}// 更新缓存@CachePut(value = "USER_CACHE", key = "#user.id")public User updateUser(User user) {return userRepository.save(user);}// 删除缓存@CacheEvict(value = "USER_CACHE", key = "#id")public void deleteUser(Long id) {userRepository.deleteById(id);}
}
  • 注解说明
    • @Cacheable:查询时优先从缓存读取
    • @CachePut:更新数据并刷新缓存
    • @CacheEvict:删除数据时移除缓存。

5. 高级配置

刷新策略(RefreshAfterWrite)

需定义CacheLoader以支持自动刷新:

@Bean
public CacheLoader<Object, Object> cacheLoader() {return new CacheLoader<>() {@Overridepublic Object load(Object key) {return loadDataFromDB(key);  // 初始加载数据}@Overridepublic Object reload(Object key, Object oldValue) {return oldValue;  // 刷新时保留旧值,异步加载新值}};
}

配置文件中需添加refreshAfterWrite=5s,并关联此Bean。

统计与监控

启用统计功能:

Caffeine.newBuilder().recordStats().build();

通过cache.stats()获取命中率、回收数量等指标。


6. 验证缓存效果

通过测试类验证缓存是否生效:

@SpringBootTest
public class CacheTest {@Autowiredprivate UserService userService;@Testpublic void testCache() {User user1 = userService.getUserById(1L);  // 首次查询,存入缓存User user2 = userService.getUserById(1L);  // 二次查询,命中缓存assertThat(user1).isSameAs(user2);}
}

常见问题

  1. 缓存未命中

    • 检查方法是否为public(注解在私有方法无效)
    • 确认缓存名称与配置一致。
  2. 配置冲突

    • 避免同时配置maximumSizemaximumWeight
    • expireAfterWrite优先级高于expireAfterAccess

通过以上步骤,可在Spring Boot 2.x中高效集成Caffeine,实现高性能本地缓存,适用于高频访问但更新较少的数据场景(如配置信息、静态数据)。



三、Caffeine使用场景

Caffeine 作为高性能本地缓存库,适用于多种需要快速数据访问和高效内存管理的场景。以下是其主要使用场景及对应的技术优势分析:


1. 高并发请求缓存

  • 场景描述:适用于高频访问的接口或热点数据,例如用户信息查询、商品详情展示等。Caffeine 通过无锁并发设计和 Window TinyLFU 算法,显著提升缓存命中率,减少数据库压力。
  • 技术优势
    • 高性能:在高并发环境下,Caffeine 的吞吐量远超 Guava Cache,其分段锁机制避免了锁竞争问题。
    • 高命中率:Window TinyLFU 算法结合 LRU 和 LFU 优点,有效保留高频访问数据,命中率比 Guava 提升 10%~20%。
  • 典型应用:Web 应用的 API 接口缓存,如电商平台的商品详情页。

2. 数据库查询缓存

  • 场景描述:用于缓存频繁查询的数据库结果,如用户常用配置、热门商品库存等,减少重复数据库访问。
  • 技术优势
    • 自动过期策略:支持 expireAfterWrite(写入后过期)和 expireAfterAccess(访问后过期),防止数据过时。
    • 内存管理:通过 maximumSize 限制缓存条目数,避免内存溢出,结合惰性删除和定时清理机制优化内存使用。
  • 典型应用:用户登录信息缓存、商品库存实时查询缓存。

3. 复杂计算结果缓存

  • 场景描述:缓存计算密集型操作的结果,如图像处理、大数据聚合分析等,避免重复计算消耗资源。
  • 技术优势
    • 异步加载:通过 AsyncLoadingCache 异步加载数据,减少主线程阻塞,提升系统响应速度。
    • 刷新机制:使用 refreshAfterWrite 定时刷新缓存,保证数据更新后的及时性,同时保留旧数据直至新数据加载完成。
  • 典型应用:推荐系统的实时计算结果缓存、图像处理后的缩略图缓存。

4. 多级缓存架构(L1缓存)

  • 场景描述:在分布式系统中作为一级本地缓存(L1),结合 Redis(L2)和数据库(L3)形成三级缓存,减少跨服务或跨节点的网络延迟。
  • 技术优势
    • 低延迟访问:本地内存访问速度极快,适合对延迟敏感的场景。
    • 灵活集成:通过 CacheLoaderWriter 接口,可无缝与 Redis 等外部缓存联动,实现数据回源和同步。
  • 典型应用:秒杀系统的库存缓存、分布式服务中的配置信息缓存。

5. 需要高灵活性和统计监控的场景

  • 场景描述:对缓存策略有定制化需求(如动态调整过期时间、监听缓存事件)或需监控缓存命中率的场景。
  • 技术优势
    • 灵活配置:支持基于大小、时间、引用等多种淘汰策略,并可自定义过期逻辑。
    • 统计功能:通过 recordStats() 启用统计,获取命中率、淘汰次数等指标,便于性能调优。
  • 典型应用:实时监控系统的缓存健康状态、需要动态调整缓存策略的业务场景。

注意事项

  1. 非分布式场景:Caffeine 仅适用于本地缓存,跨节点数据需结合 Redis 等分布式缓存。
  2. 内存限制:需根据应用内存合理设置 maximumSize 或权重,避免 OOM 问题。
  3. 数据一致性:本地缓存可能导致多实例间数据不一致,需通过过期时间或事件通知机制解决。

总结

Caffeine 凭借其高性能、高命中率和灵活的配置,成为高并发、低延迟场景下的首选本地缓存库。尤其适合作为一级缓存与 Redis 等组成多级缓存架构,或用于需要快速响应和复杂策略管理的业务场景。实际应用中需结合具体需求调整淘汰策略和内存配置,以最大化其优势。

更多用法:

SpringBoot:第五篇 集成Guava(本地缓存+分布式缓存)

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

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

相关文章

Linux工作台文件操作命令全流程解析

全文目录 1 确认当前工作路径2 导航与目录管理2.1 关键命令2.2 逻辑衔接 3 文件基础操作3.1 创建 → 备份 → 重命名 → 清理3.2 文件查看和编辑3.3 文件链接3.4 文件diff 4 文件权限与所有权管理5 文件打包与归档6 参考文献 写在前面 shell是一种命令解释器&#xff0c;它提供…

LeetCode第183题_从不订购的客户

LeetCode 第183题&#xff1a;从不订购的客户 题目描述 表: Customers ---------------------- | Column Name | Type | ---------------------- | id | int | | name | varchar | ---------------------- id 是该表的主键。 该表包含消费者的 id 和…

c语言的常用关键字

c语言的常用关键字 c语言的关键字表示数据类型的关键字autocharfloatdoubleintlongshortvoidsignedstruct、enum、unionunsigned 表示分支语句的关键字ifelseswitchbreakcasecontinuedefault 表示循环语句的关键字whiledoforgoto 用于修饰变量或函数的关键字constconst修饰变量…

MCU通用输入输出端口(GPIO)设计指南

在嵌入式系统开发中&#xff0c;MCU的GPIO接口是一个基础但非常实用的功能模块。GPIO全称是通用输入输出端口&#xff0c;它让MCU可以灵活地与外部设备进行交互。 GPIO的主要特点包括&#xff1a; 多功能性&#xff1a;每个引脚都可以单独配置为输入或输出 可编程性&#xff…

STM32完整内存地址空间分配详解

在STM32这类基于ARM Cortex-M的32位微控制器中&#xff0c;整个4GB的地址空间(从0x00000000到0xFFFFFFFF)有着非常系统化的分配方案&#xff0c;每个区域都有其特定的用途。下面我将详细介绍这些地址区域的分配及其功能&#xff1a; STM32完整内存地址空间分配详解(0x00000000…

实现水平垂直居中的多种方法

在前端开发中&#xff0c;元素的居中是一个常见但又经常让人头疼的问题。本文将全面总结各种CSS居中方法&#xff0c;特别是如何实现一个div的水平垂直居中。 为什么居中这么重要&#xff1f; 居中布局是现代网页设计中最基础也最重要的布局方式之一。无论是导航菜单、登录框…

如何实现服务的自动扩缩容(Auto Scaling)

在云计算和分布式系统的时代,系统的弹性和适应性已成为企业构建高效IT基础设施的核心需求。自动扩缩容(Auto Scaling)作为一种关键技术,旨在根据实时负载变化动态调整计算资源,以确保系统性能稳定,同时优化资源利用效率。简单来说,自动扩缩容是指系统能够根据预设规则或…

uniapp+vue3+ts 使用canvas实现安卓端、ios端及微信小程序端二维码生成及下载

加粗样式uniapp多端生成带二维码海报并保存至相册的实现 在微信小程序开发中&#xff0c;我们常常会遇到生成带有二维码的海报并保存到手机相册的需求&#xff0c;比如分享活动海报、产品宣传海报等。今天就来和大家分享一下如何通过代码实现这一功能。 准备工作 在开始之前&am…

架构师面试(三十八):注册中心架构模式

题目 在微服务系统中&#xff0c;当服务达到一定数量时&#xff0c;通常需要引入【注册中心】组件&#xff0c;以方便服务发现。 大家有没有思考过&#xff0c;注册中心存在的最根本的原因是什么呢&#xff1f;注册中心在企业中的最佳实践是怎样的&#xff1f;注册中心的服务…

Day.js和Moment.js对比,日期时间库怎么选?

在JavaScript的日期处理库中&#xff0c;Moment.js 和 Day.js 是两个非常流行的选择。本文将基于从npmtrends的数据&#xff0c;对这两个库进行详细的对比分析。 Moment.js的重度使用者。凡是遇到时间和日期的操作&#xff0c;就把Moment.js引用上。 直到有天我发现加载的mome…

罗默如何用木星卫星“宇宙钟表”测量光速?

一、17世纪的“宇宙级实验” 1676年&#xff0c;丹麦天文学家奥勒罗默&#xff08;Ole Rmer&#xff09;在巴黎天文台做出惊人发现&#xff1a; 木星卫星的“迟到早退”现象&#xff0c;竟能揭示光速的秘密&#xff01; 通过观察木卫一&#xff08;Io&#xff09;的轨道周期变…

deepseek 技巧整理

1、导出word 和excel 功能&#xff0c;在使用以下提示词。 请帮我列出减肥期间可以吃的水果&#xff0c;并分析该水果含有的营养元素&#xff0c;以表格的形式星现。1.要以html的方式输出 2.要可以直接运行 3.页面要提供可以直接下载word和excel功能

思考软件框架

数据库是达梦数据库 假定里面有40张表&#xff0c;软件的业务逻辑比较复杂。 当然&#xff0c;依然是对数据库中数据的增&#xff0c;删&#xff0c;改&#xff0c;查&#xff0c;组合&#xff0c;显示。 但是也涉及到多种软件&#xff0c;多台设备之间的通信。 我们可以使用…

探索 Disruptor:高性能并发框架的奥秘

在当今的软件开发领域&#xff0c;处理高并发场景是一项极具挑战性的任务。传统的并发解决方案&#xff0c;如基于锁的队列&#xff0c;往往在高负载下表现出性能瓶颈。而 Disruptor 作为一个高性能的并发框架&#xff0c;凭借其独特的设计和先进的技术&#xff0c;在处理海量数…

前端面经-VUE3篇--vue3基础知识(一)插值表达式、ref、reactive

一、计算属性(computed) 计算属性&#xff08;Computed Properties&#xff09;是 Vue 中一种特殊的响应式数据&#xff0c;它能基于已有的响应式数据动态计算出新的数据。 计算属性有以下特性&#xff1a; 自动缓存&#xff1a;只有当它依赖的响应式数据发生变化时&#xff…

数据结构6 · BinaryTree二叉树模板

代码函数功能顺序如下&#xff1a; 1&#xff1a;destroy&#xff1a;递归删除树 2&#xff1a;copy&#xff1a;复制二叉树 3&#xff1a;preOrder&#xff1a;递归前序遍历 4&#xff1a;inOrder&#xff1a;递归中序遍历 5&#xff1a;postOrder&#xff1a;递归后续遍…

C++/SDL进阶游戏开发 —— 双人塔防游戏(代号:村庄保卫战 13)

&#x1f381;个人主页&#xff1a;工藤新一 &#x1f50d;系列专栏&#xff1a;C面向对象&#xff08;类和对象篇&#xff09; &#x1f31f;心中的天空之城&#xff0c;终会照亮我前方的路 &#x1f389;欢迎大家点赞&#x1f44d;评论&#x1f4dd;收藏⭐文章 文章目录 十…

强化学习之基于无模型的算法之时序差分法

2、时序差分法(TD) 核心思想 TD 方法通过 引导值估计来学习最优策略。它利用当前的估计值和下一个时间步的信息来更新价值函数&#xff0c; 这种方法被称为“引导”&#xff08;bootstrapping&#xff09;。而不需要像蒙特卡罗方法那样等待一个完整的 episode 结束才进行更新&…

AE/PR模板 100个现代文字标题动态排版效果动画 Motion Titles

Motion Titles是一个令人惊艳的AE/PR模板&#xff0c;提供了100个现代文字标题的动态排版效果动画。这些动画效果能够为你的项目增添视觉冲击力和专业感&#xff0c;为文字标题注入活力和动感。该模板适用于Adobe After Effects CC或更高版本以及Adobe Premiere Pro 2020或更高…

【AI提示词】二八法则专家

提示说明 精通二八法则&#xff08;帕累托法则&#xff09;的广泛应用&#xff0c;擅长将其应用于商业、管理、个人发展等领域&#xff0c;深入理解其在不同场景中的具体表现和实际意义。 提示词 # Role: 二八法则专家## Profile - language: 中文 - description: 精通二八法…