SpringBoot使用本地缓存——Caffeine

SpringBoot使用本地缓存——Caffeine

缓存,想必大家都用过,将常用的数据存储在缓存上能在一定程度上提升数据存取的速度。这正是局部性原理的应用。之前用的缓存大多是分布式的,比如Redis。使用Redis作为缓存虽然是大多数系统的选择,但是需要另起服务,且会增加一定的耗时在数据传输上。对于一些小型应用,用Redis就有点大材小用了,此时便可以使用本地缓存。

本地缓存的技术选型:

  • 使用 ConcurrentHashMap 作为缓存

    这个是最简单的缓存使用,但是没有一定的内存淘汰策略,用作缓存来使用,功能比较单一。需要开发人员进行定制化开发。

  • Guava Cache

    Guava是Google团队开源的一款 Java 核心增强库,包含集合、并发原语、缓存、IO、反射等工具箱,性能和稳定性上都有保障,应用十分广泛,强烈推荐。其中 Guava Cache 支持很多特性,比如:支持最大容量限制、支持两种过期删除策略(插入时间和访问时间)、支持简单的统计功能、基于LRU算法实现

  • 本文将要介绍的Caffeine缓存

    Caffeine是一个高性能的Java本地缓存库,设计用于提供快速响应时间和高并发处理能力。它具有类似于Guava缓存的简单易用的API,同时也提供了许多额外的功能和性能优化。Caffeine支持缓存大小限制、缓存过期策略、异步加载数据等特性,可以帮助开发人员在应用程序中有效地管理和优化缓存。Caffeine还提供了可自定义的缓存策略和监听器,以帮助开发人员根据实际需求定制缓存行为。

  • 基于Ehcache实现本地缓存

    Ehcache是一个流行的Java开源缓存框架,用于在应用程序中管理缓存数据。它被广泛用于提高应用程序性能,减少数据库访问频率,和减少网络开销。同Caffeine和Guava Cache相比,Ehcache的功能更加丰富,扩展性更强。

Caffeine本地缓存

在项目开发中,为提升系统性能,减少 IO 开销,采用本地缓存是必不可少的。最常见的本地缓存是 Guava 和 Caffeine。Caffeine 是基于 Google Guava Cache 设计经验改进的结果,相较于 Guava 在性能和命中率上更具有效率,你可以认为其是 Guava Plus版本。

使用步骤

步骤 1: 添加依赖

<dependency><groupId>com.github.ben-manes.caffeine</groupId><artifactId>caffeine</artifactId><version>3.1.5</version> <!-- 确保使用最新版本 -->
</dependency><!-- Spring Boot Cache 的依赖 -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-cache</artifactId>
</dependency>

步骤 2: 配置 Caffeine 缓存管理器

package com.supermap.ai.agent.config;import com.github.benmanes.caffeine.cache.Caffeine;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.CacheManager;
import org.springframework.cache.caffeine.CaffeineCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;import java.util.concurrent.TimeUnit;/*** @Author: wangrongyi* @Date: 2024/7/8 14:02* @Description: 缓配配置类*/
@Configuration
@Slf4j
public class CaffeineConfig {@Beanpublic CacheManager cacheManager() {CaffeineCacheManager cacheManager = new CaffeineCacheManager();//Caffeine配置Caffeine<Object, Object> caffeine = Caffeine.newBuilder()//最后一次写入后经过固定时间过期.expireAfterWrite(600, TimeUnit.SECONDS)//maximumSize=[long]: 缓存的最大条数.maximumSize(1000);cacheManager.setCaffeine(caffeine);log.info("缓存配置 CacheManager 初始化");return cacheManager;}@Beanpublic Cache<String, Object> caffeineCache() {log.info("缓存配置 Cache 初始化");return Caffeine.newBuilder()// 设置最后一次写入或访问后经过固定时间过期.expireAfterWrite(600, TimeUnit.SECONDS)// 初始的缓存空间大小.initialCapacity(1000)// 缓存的最大条数.maximumSize(1000).build();}
}

Caffeine配置参数说明:

initialCapacity=[integer]: 初始的缓存空间大小
maximumSize=[long]: 缓存的最大条数
maximumWeight=[long]: 缓存的最大权重
expireAfterAccess=[duration]: 最后一次写入或访问后经过固定时间过期
expireAfterWrite=[duration]: 最后一次写入后经过固定时间过期
refreshAfterWrite=[duration]: 创建缓存或者最近一次更新缓存后经过固定的时间间隔,刷新缓存
weakKeys: 打开key的弱引用
weakValues:打开value的弱引用
softValues:打开value的软引用
recordStats:开发统计功能 注意:
expireAfterWrite和expireAfterAccess同事存在时,以expireAfterWrite为准。
maximumSize和maximumWeight不可以同时使用
weakValues和softValues不可以同时使用

注意: CacheManager 是使用注解形式时需要注入的Bean,Cache是在代码中显示使用时需要注入的,可以注入多个Bean,用名字区分,达到使用不通的缓存配置的效果。比如对过期时间有不通的要求,那么就可以注入两个过期时间不同的 CacheManager ,Bean的名字要做区分,在使用 @Cacheable 调用缓存时,便可以显示指定不同的 cacheManager。

步骤 3: 使用缓存

有两种使用缓存的方式:注解使用、代码显示使用

  • 注解使用

        // 获取缓存@GetMapping("/getCache")@Cacheable(value = "cache", key = "'key'")public String getCache() throws InterruptedException {Thread.sleep(3000);return "getCache";}// 设置缓存@GetMapping("/setCache")@CachePut(value = "cache", key = "'key'")public String setCache() throws InterruptedException {Thread.sleep(3000);return "setCache";}// 删除缓存@GetMapping("/delCache")@CacheEvict(value = "cache", key = "'key'")public String delCache() throws InterruptedException {Thread.sleep(3000);return "delCache";}
    

    注解使用说明:

    • @EnableCaching

      开启缓存功能,一般放在启动类上。

    • @CacheConfig

      当我们需要缓存的地方越来越多,你可以使用@CacheConfig(cacheNames = {“cacheName”})注解在 class 之上来统一指定value的值,这时可省略value,如果你在你的方法依旧写上了value,那么依然以方法的value值为准。

    • @Cacheable

      根据方法对其返回结果进行缓存,下次请求时,如果缓存存在,则直接读取缓存数据返回;如果缓存不存在,则执行方法,并把返回的结果存入缓存中。一般用在查询方法上。

      属性/方法名解释
      value缓存名,必填,它指定了你的缓存存放在哪块命名空间
      cacheNames与 value 差不多,二选一即可
      key可选属性,可以使用 SpEL 标签自定义缓存的key
      keyGeneratorkey的生成器。key/keyGenerator二选一使用
      cacheManager指定缓存管理器
      cacheResolver指定获取解析器
      condition条件符合则缓存
      unless条件符合则不缓存
      sync是否使用异步模式,默认为false
    • @CachePut

      使用该注解标志的方法,每次都会执行,并将结果存入指定的缓存中。其他方法可以直接从响应的缓存中读取缓存数据。一般用在新增方法上。

      属性/方法名解释
      value缓存名,必填,它指定了你的缓存存放在哪块命名空间
      cacheNames与 value 差不多,二选一即可
      key可选属性,可以使用 SpEL 标签自定义缓存的key
      keyGeneratorkey的生成器。key/keyGenerator二选一使用
      cacheManager指定缓存管理器
      cacheResolver指定获取解析器
      condition条件符合则缓存
      unless条件符合则不缓存
    • @CacheEvict

      使用该注解标志的方法,会清空指定的缓存。一般用在更新或者删除方法上。

      属性/方法名解释
      value缓存名,必填,它指定了你的缓存存放在哪块命名空间
      cacheNames与 value 差不多,二选一即可
      key可选属性,可以使用 SpEL 标签自定义缓存的key
      keyGeneratorkey的生成器。key/keyGenerator二选一使用
      cacheManager指定缓存管理器
      cacheResolver指定获取解析器
      condition条件符合则缓存
      allEntries是否清空所有缓存,默认为 false。如果指定为 true,则方法调用后将立即清空所有的缓存
      beforeInvocation是否在方法执行前就清空,默认为 false。如果指定为 true,则在方法执行前就会清空缓存
    • @Caching

      该注解可以实现同一个方法上同时使用多种注解。可从其源码看出:

      image-20240716171300420

  • 代码显示使用

        @Autowiredprivate Cache<String, Object> cache;@GetMapping("/getCacheInfo")public void getCacheInfo() throws InterruptedException {String s = (String) cache.getIfPresent("key");if (s == null) {cache.put("key", "value");Thread.sleep(3000);}log.info("cache:{}", cache.getIfPresent("key"));}
    

    显示使用时需要注意处理并发读写,防止并发读写造成缓存不一致问题。

总结:使用Caffeine作为本地缓存能极大增加缓存数据的访问效率,提升读取性能。不过,本地缓存的使用受限于本地缓存的大小,所以面对缓存很大以及复杂的数据结构还是考虑用第三方的缓存服务,比如Redis。

关注不迷路。come on 在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

基于springboot和mybatis的RealWorld后端项目实战三之添加swagger

pom.xml添加依赖 <dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger2</artifactId><version>2.9.2</version></dependency><dependency><groupId>io.springfox</groupId><arti…

Linux多进程

父子进程 一个进程可以创建另一个进程吗&#xff1f; 干想代码可能很犹豫&#xff0c;因为我们从来都没有见过创建新进程的代码。但是&#xff1a; 短短几秒钟&#xff0c;就创建了两个进程。这些进程是系统创建的吗&#xff1f;不是。一个是小爱同学创建的&#xff0c;另一个…

CSS实现加载动画

需求&#xff1a;在开发过程中&#xff0c;我们会经常遇到一些基本的加载动画需求。这里我们简单介绍几个加载动画&#xff0c;主要是通过使用css的animation和transition的属性进行实现的动画和过渡效果。 语法&#xff1a; animation: name duration timing-function delay…

电脑录屏录音软件,拥有这3款就足够

在信息化的时代&#xff0c;电脑早已成为我们生活中的得力助手。而电脑录屏录音软件&#xff0c;就像是一位能够帮助我们捕捉到屏幕上一切的魔法师&#xff0c;用其独特的魔力&#xff0c;将屏幕上的精彩瞬间和动人声音一一捕捉&#xff0c;永久珍藏。 电脑录屏与录音并不是一…

Java | Leetcode Java题解之第238题除自身以外数组的乘积

题目&#xff1a; 题解&#xff1a; class Solution {public int[] productExceptSelf(int[] nums) {int length nums.length;// L 和 R 分别表示左右两侧的乘积列表int[] L new int[length];int[] R new int[length];int[] answer new int[length];// L[i] 为索引 i 左侧…

LabVIEW机器学习实现外观检测

介绍如何利用LabVIEW平台结合机器学习技术实现对被测样品的外观检测。详细说明了硬件选择、算法使用、操作步骤以及注意事项。 硬件选择 工业相机&#xff1a;高分辨率工业相机&#xff08;如Basler、FLIR等&#xff09;用于采集样品的图像。 照明设备&#xff1a;均匀的LED照…

亲子母婴行业媒体邀约宣发资源

传媒如春雨&#xff0c;润物细无声&#xff0c;大家好&#xff0c;我是51媒体网胡老师。 亲子母婴行业是一个综合性的产业&#xff0c;涉及多个领域&#xff0c;包括儿童食品&#xff0c;儿童玩具&#xff0c;服装&#xff0c;洗护&#xff0c;月子中心&#xff0c;母婴护理&a…

江科大SPI教程听课笔记

原理部分我打算听江科大的课复习一下&#xff0c;代码部分工作大概率用HAL库敲了。 SPI(Serial Peripheral Interface)是由Motorola公司开发的一种通用数据总线。 硬件资源方面需要四根通信线:SCK(Serial Clock)、MOSI(Master Output Slave Input)、MISO (Master Input Slave…

苏州大视通特种镜头规格书-360内度壁镜头-型号DST36023066

360内壁检测镜头 产品特点 专为内壁检测开发的特种镜头&#xff1b;可实现大视场角的内壁检测&#xff1b;最大支持直径 5mm-120mm&#xff0c;深度 4mm-120mm的内孔检测&#xff1b;最大支持 2/3”相机&#xff0c;成像圈为 φ6mm&#xff1b;可定制光阑孔径以调节亮度和景深…

【FPGA】优雅地使用ILA进行FPGA硬件调试

Vivado&#xff08;Vitis&#xff09;版本&#xff1a;2020.2FPGA开发板&#xff1a;Microphase Z7-Lite 7020开发板 FPGA设计调试流程 FPGA开发是一个不断迭代的过程&#xff0c;一般的FPGA设计流程一般包含下面几个步骤&#xff1a; 硬件架构和算法验证&#xff1a;实现需要…

CV每日论文--2024.7.16

1、Radiance Fields from Photons 中文标题&#xff1a;光子的辐射场 简介&#xff1a;神经辐射场(NeRFs)已成为从多个视角捕获的图像进行高质量视图合成的事实标准方法。然而,在野外环境下捕获图像时,仍存在许多挑战,例如低光、高动态范围或快速运动导致的模糊重建和明显的伪…

Apache trino的ldap认证开启

作者&#xff1a;櫰木 1、背景 由于trino 默认没有开启用户认证体系&#xff0c;需要ldap用户进行认证。开启tls和ldap用户认证&#xff0c;提高安全性。 2、配置 前置条件。 trino 集群已经部署完成 ldap 服务 openjdk 版本大于11.0.17 生成证书 keytool -genkeypair…

前端pc和小程序接入快递100(跳转方式和api方式)====实时查询接口

文章目录 跳转方式微信小程序&#xff08;我以uniapp为例&#xff09;pc api接入说明关于签名计算成功示例 跳转方式 没有任何开发成本&#xff0c;直接一键接入 可以直接看官方文档 https://www.kuaidi100.com/openapi/api_wxmp.shtml 微信小程序&#xff08;我以uniapp为例…

SQL,python,knime将数据混合的文字数字拆出来,合并计算(学习笔记)

将下面将数据混合的文字数字拆出来&#xff0c;合并计算 一、SQL解决&#xff1a; ---创建表插入数据 CREATE TABLE original_data (id INT AUTO_INCREMENT PRIMARY KEY,city VARCHAR(255),value DECIMAL(10, 1) );INSERT INTO original_data (city, value) VALUES (上海0.5…

十一、Java多线程(模块16-17)

十一、Java多线程 day08-线程安全,死锁,状态,通讯,线程池今日目标1 线程安全1.1 线程安全产生的原因注意 : 以上代码是有问题 , 接下来继续改进通过上述代码的执行结果 , 发现了出现了负号票 , 和相同的票 , 数据有问题 1.2 线程的同步1.3 同步代码块1.4 同步方法1.5 Lock锁 2 …

电脑QQ录屏,2个方法轻松搞定电脑录屏

“电脑QQ也有录屏功能吗&#xff1f;我使用电脑QQ多年居然不知道QQ还有录屏功能。电脑QQ录屏功能怎么使用啊&#xff1f;有没有会的小伙伴可以教教我&#xff1f;先谢谢大家啦&#xff01;” QQ作为陪伴我们多年的“老朋友”&#xff0c;它不仅是我们与朋友家人沟通的重要桥梁…

揭秘OpenCV:探寻视觉世界的轮廓之谜

揭秘OpenCV&#xff1a;探寻视觉世界的轮廓之谜 1. 介绍1.1 什么是轮廓检测&#xff1f;1.2 OpenCV 中的轮廓检测应用 2. 准备工作2.1 安装 OpenCVWindows 用户:macOS 用户:Linux 用户: 2.2 加载图像2.3 图像处理&#xff08;转换图像颜色空间&#xff09;2.4 表格描述 3. 轮廓…

对某根域的一次渗透测试

前言 两个月之前的一个渗透测试项目是基于某网站根域进行渗透测试&#xff0c;发现该项目其实挺好搞的&#xff0c;就纯粹的没有任何防御措施与安全意识所以该项目完成的挺快&#xff0c;但是并没有完成的很好&#xff0c;因为有好几处文件上传没有绕过&#xff08;虽然从一个…

前端基础之Flex布局

【图书推荐】《HTML5CSS3 Web前端开发与实例教程&#xff08;微课视频版&#xff09;》-CSDN博客 Flex布局概述 Flex布局全称为Flexible Box布局模式&#xff0c;是CSS3规范中一项革命性的强大布局技术。它以“弹性”为核心理念&#xff0c;旨在提供一种更为灵活且功能丰富的…

论文复现丨物流中心选址问题:蜘蛛猴算法求解

路径优化系列文章&#xff1a; 1、路径优化历史文章2、物流中心选址问题论文复现丨改进蜘蛛猴算法求解 物流中心选址问题 一般物流中心选址问题是指&#xff1a;在有限的用户(即需求点)中找出一定数量的地点建立配送中心&#xff0c;实现从物流中心到用户之间的配送&#xf…