高性能 Java 本地缓存 Caffeine 框架介绍及在 SpringBoot 中的使用

news2024/11/15 12:58:32

在现代应用程序中,缓存是一种重要的性能优化技术,它可以显著减少数据访问延迟,降低服务器负载,提高系统的响应速度。特别是在高并发的场景下,合理地使用缓存能够有效提升系统的稳定性和效率。

Caffeine 是一个高性能的 Java 本地缓存库,以其近乎最佳的命中率和灵活的配置选项在众多缓存解决方案中脱颖而出。它的设计目标是提供一个简单但功能强大的缓存实现,支持多种缓存策略,包括基于大小的淘汰、基于时间的过期、弱引用和软引用等。


文章目录

      • 1、Caffeine Cache 介绍
      • 2、Caffeine Cache 使用示例
        • 2.1、依赖引入
        • 2.2、示例代码
      • 3、Caffeine Cache 在 SpringBoot 中的使用
        • 3.1、依赖引入
        • 3.2、配置文件
        • 3.3、启用缓存
        • 3.4、配置缓存管理器
        • 3.5、使用缓存


1、Caffeine Cache 介绍

Caffeine 是一个用于 Java 的缓存库,其设计目标是高性能,和近乎最佳的命中率。缓存库的主要功能是存储和快速检索数据,以减少直接访问数据源(例如数据库或远程服务)的次数,从而提高应用程序的性能。Caffeine 的 “高性能” 表示它在处理缓存操作时速度很快,并且占用的资源较少。“近乎最佳的命中率” 指的是 Caffeine 在缓存命中(即请求的数据已经存在于缓存中)方面表现非常出色。高命中率意味着大多数数据请求都可以直接从缓存中获得,而无需访问原始数据源,从而大大提高了效率和响应速度。

image-20240726183556025

Caffeine 是受 Google Guava 提供内存缓存 API 的启发。借着 Guava 的思想优化了算法发展而来。

Caffeine 缓存与并发映射(ConcurrentMap)类似,但不完全相同。最根本的区别在于,并发映射会保存所有添加到其中的元素,直到它们被显式地移除。而缓存通常配置为自动驱逐条目,以限制其内存占用。在某些情况下,即使缓存不驱逐条目,LoadingCache 或 AsyncLoadingCache 也可能非常有用,因为它们可以自动加载缓存。

Caffeine 提供灵活的构建方式来创建具有以下可选功能组合的缓存:

  • 自动加载缓存条目,可以选择异步方式
  • 基于大小的驱逐,当超过最大值时根据使用频率和最近使用时间进行驱逐
  • 基于时间的条目过期,依据最后访问时间或最后写入时间进行测量
  • 当首次请求陈旧条目时异步刷新
  • 键自动包装成弱引用
  • 值自动包装成弱引用或软引用
  • 驱逐(或其他方式移除)条目的通知
  • 将写操作传播到外部资源
  • 累积缓存访问统计信息

为了改进集成,扩展模块中提供了 JSR-107 JCache 和 Guava 适配器。JSR-107 标准化了基于 Java 6 的 API,以最小化特定供应商代码的代价来实现功能和性能。Guava 的 Cache 是 Caffeine 的前身库,这些适配器提供了一个简单的迁移策略。


2、Caffeine Cache 使用示例

2.1、依赖引入

Caffeine 可以通过 Maven 或 Gradle 依赖引入,对于 Java 11 或更高版本,使用 3.x 其他版本则使用 2.x

Maven 依赖:

<!-- https://mvnrepository.com/artifact/com.github.ben-manes.caffeine/caffeine -->
<dependency>
    <groupId>com.github.ben-manes.caffeine</groupId>
    <artifactId>caffeine</artifactId>
    <version>2.9.3</version>
</dependency>
2.2、示例代码

可以参照以下示例代码来使用 CaffeineCache:

import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;

import java.util.concurrent.TimeUnit;

public class CaffeineCacheExample {
    public static void main(String[] args) {
        // 初始化缓存
        Cache<String, String> cache = Caffeine.newBuilder()
                // 设置最大缓存条目数
                .maximumSize(100)
                // 设置条目在最后一次访问后10分钟过期
                .expireAfterAccess(10, TimeUnit.MINUTES)
                // 设置条目在写入后10分钟过期
                .expireAfterWrite(10, TimeUnit.MINUTES)
                // 设置键使用弱引用
                .weakKeys()
                // 设置值使用软引用
                .softValues()
                // 构建缓存
                .build();

        // 添加一些条目到缓存中
        cache.put("key1", "value1");
        cache.put("key2", "value2");

        // 获取并打印缓存条目
        System.out.println("key1: " + cache.getIfPresent("key1"));
        System.out.println("key2: " + cache.getIfPresent("key2"));

        // 模拟访问 "key1"
        cache.getIfPresent("key1");

        // 等待一段时间后再获取缓存条目
        try {
            // 等待6秒
            Thread.sleep(6000); 
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }

        // 获取并打印缓存条目
        System.out.println("key1 (after 6 seconds): " + cache.getIfPresent("key1"));
        System.out.println("key2 (after 6 seconds): " + cache.getIfPresent("key2"));

        // 模拟再等待时间超过10分钟,检查过期
        try {
            // 等待10分钟
            Thread.sleep(600000); 
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }

        // 获取并打印缓存条目,预期缓存条目已过期
        System.out.println("key1 (after 10 minutes): " + cache.getIfPresent("key1"));
        System.out.println("key2 (after 10 minutes): " + cache.getIfPresent("key2"));
    }
}

3、Caffeine Cache 在 SpringBoot 中的使用

在 Spring Boot 应用中,可以通过配置文件和注解来简化对 Caffeine 缓存的集成和管理。

3.1、依赖引入

pom.xml 文件中添加 Caffeine 和 Spring Boot 缓存依赖:

<dependencies>
    <!-- Spring Boot Starter Cache -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-cache</artifactId>
    </dependency>
    <!-- Caffeine Cache -->
    <dependency>
        <groupId>com.github.ben-manes.caffeine</groupId>
        <artifactId>caffeine</artifactId>
    </dependency>
</dependencies>
3.2、配置文件

application.yml 中配置 Caffeine 缓存属性:

spring:
  cache:
    type: caffeine
    cache-names: myCache
    caffeine:
      spec: maximumSize=100,expireAfterWrite=10m,expireAfterAccess=10m

这里 spec 属性用于设置缓存策略,包括最大缓存大小 (maximumSize)、写入后的过期时间 (expireAfterWrite),以及访问后的过期时间 (expireAfterAccess)。

3.3、启用缓存

在 Spring Boot 应用主类上添加 @EnableCaching 注解:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;

@SpringBootApplication
@EnableCaching
public class ExampleApplication {
    public static void main(String[] args) {
        SpringApplication.run(ExampleApplication.class, args);
    }
}
3.4、配置缓存管理器

创建一个配置类来自定义缓存管理器:

import com.github.benmanes.caffeine.cache.Caffeine;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.caffeine.CaffeineCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.concurrent.TimeUnit;

@Configuration
@EnableCaching
public class CacheConfig {

    @Bean
    public CaffeineCacheManager cacheManager() {
        CaffeineCacheManager cacheManager = new CaffeineCacheManager("myCache");
        cacheManager.setCaffeine(Caffeine.newBuilder()
                .maximumSize(100)
                .expireAfterWrite(10, TimeUnit.MINUTES)
                .expireAfterAccess(10, TimeUnit.MINUTES));
        return cacheManager;
    }
}
3.5、使用缓存

在需要缓存的方法上添加 @Cacheable 注解:

import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

@Service
public class MyService {

    @Cacheable("myCache")
    public String getData(String key) {
        // 模拟获取数据的过程
        return "Data for " + key;
    }
}
  • @Cacheable("myCache"):注解告诉 Spring 该方法的返回值应该被缓存。缓存的名字是 myCache
  • @RequestParam String key:注解从请求参数中获取 key 的值并传递给 getData 方法;
  • 缓存命中:如果缓存中存在对应 key 的值,则直接返回缓存值,否则执行方法体并将结果存入缓存。

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

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

相关文章

Java基础巩固——JDK 8、9新增接口的特性(接口中定义非抽象方法、静态方法和私有方法)

#Java学了这么久&#xff0c;项目也做了&#xff1f;基础知识还不巩固&#xff1f;快来关注我的这篇系列博客——Java基础复习巩固吧# 目录 引言 一、JDK8新特性&#xff1a;允许在接口中定义非抽象方法和静态方法。 注意事项 二、JDK9新特性&#xff1a;允许在接口中定义p…

【推研小灶】复旦与南大之间:一次独特的计算机保研之旅

写在前面 上午10点填完志愿等待复试通知&#xff0c;利用这段时间记录一下我简短的夏令营和预推免。今年变为线下之后&#xff0c;部分学校的入营情况、考核方式有明显变化。加上CS方向保研名额总体变多&#xff0c;形势有点小乱&#xff0c;甚至填报系统都在9.29中秋节当天&a…

AMQP-核心概念-3

本文参考以下链接摘录翻译&#xff1a; https://www.rabbitmq.com/tutorials/amqp-concepts 队列&#xff08;Queues&#xff09; AMQP 0-9-1模型中的队列和其他消息任务队列系统中的队列非常相似&#xff1a;它们用于存储被应用消费的消息。队列和交换机有一些相同的属性&…

2024.7.28周报

目录 摘要 ABSTRACT 一、文献阅读 一、题目 二、摘要 三、创新点 四、文献解读 一、Introduction 二、Saint-Venant方程 三、应用于水道建模的PINN 四、真实场景 五、结论 摘要 本周阅读了一篇题目为Physics-Informed Neural Networks for Modeling Water Flows …

免费【2024】springboot 毕业生学历证明系统

博主介绍&#xff1a;✌CSDN新星计划导师、Java领域优质创作者、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和学生毕业项目实战,高校老师/讲师/同行前辈交流✌ 技术范围&#xff1a;SpringBoot、Vue、SSM、HTML、Jsp、PHP、Nodejs、Python、爬虫、数据可视化…

vite5+vue3开发阅读APP实战笔记20240725

目前界面长成这样&#xff1a; 配置别名 修改vite.config.js import {defineConfig} from vite import vue from vitejs/plugin-vue import path from "path"// https://vitejs.dev/config/ export default defineConfig({server: {open: true,port: 8088,},plug…

Can we Deploy Web Application in Azure OpenAI of Production Level

题意&#xff1a;我们可以在Azure OpenAI中部署生产级别的Web应用程序吗 问题背景&#xff1a; I have created azure ai search service and used Text split skillset and made index. I also deployed a web Application but have a question that If I want to create to …

嵌入式Linux学习: 设备树实验

设备树&#xff08;DeviceTree&#xff09;是一种硬件描述机制&#xff0c;用于在嵌入式系统和操作系统中描述硬件设备的特性、连接关系和配置信息。它提供了一种与平台无关的方式来描述硬件&#xff0c;使得内核与硬件之间的耦合度降低&#xff0c;提高了系统的可移植性和可维…

实战解读:Llama Guard 3 Prompt Guard

前序研究&#xff1a;实战解读&#xff1a;Llama 3 安全性对抗分析 近日&#xff0c;腾讯朱雀实验室又针对 Llama 3.1 安全性做了进一步解读。 2024年7月23日晚&#xff0c;随着Llama3.1的发布&#xff0c;Meta正式提出了“Llama系统”的概念&#xff0c;通过系统级的安全组件对…

黄景仁,笔墨间的一抹清寒

黄景仁&#xff0c;字汉镛&#xff0c;一字仲则&#xff0c;号鹿菲子&#xff0c;生于乾隆十四年&#xff08;公元1749年&#xff09;&#xff0c;卒于乾隆四十八年&#xff08;公元1783年&#xff09;&#xff0c;享年仅35岁。他是宋代大诗人黄庭坚的后裔&#xff0c;出生于常…

Feign-微服务通信(Feign远程调⽤ Feign简介 基本使⽤ ⾃定义配置 Feign使⽤优化)

目录 一、Feign远程调⽤ 二、Feign简介 三、基本使⽤ 1. 加⼊Fegin的依赖 2. 在主类上添加Fegin的注解 3. 创建⼀个service&#xff0c; 并使⽤Fegin实现微服务调⽤ 4. 修改controller代码&#xff0c;并启动验证 5. 重启order微服务,查看效果 四、⾃定义配置…

java.lang.ThreadLocal

ThreadLocal万字总结https://blog.csdn.net/sinat_33921105/article/details/103295070 key的唯一性 一个线程中的多个ThreadLocal变量如何存储、如何保证唯一性&#xff1f; 每一个 ThreadLocal<T> tl new ThreadLocal<>(); 创建出来都有一个不变且唯一的thre…

Codeforces Round 949 (Div. 2) B. Turtle and an Infinite Sequence (找规律,位运算)

不知道为什么会有找规律这种nt题型。 首先每一秒都会发生 a i a i − 1 ∣ a i ∣ a i 1 a_i a_{i-1} | a_i | a_{i1} ai​ai−1​∣ai​∣ai1​&#xff0c;如果我们多写几步&#xff1a; a i 2 a i − 1 1 ∣ a i 1 ∣ a i 1 1 a i − 2 ∣ a i − 1 ∣ a i ∣ a i −…

力扣高频SQL 50 题(基础版)第三题

文章目录 力扣高频SQL 50 题&#xff08;基础版&#xff09;第三题1148.文章浏览题目说明思路分析实现过程准备数据实现方式结果截图 力扣高频SQL 50 题&#xff08;基础版&#xff09;第三题 1148.文章浏览 题目说明 Views 表&#xff1a; ---------------------- | Colu…

用 python 求拥塞控制模型欧拉数值解

昨天使用 scipy 的 odeint 模拟了 E_best 的微分方程组模型(参见 用 python scipy 库模拟拥塞控制模型)&#xff0c;但我觉得那个模型中处理 z 时不够优雅&#xff0c;只是一个负反馈&#xff0c;并未体现 “排队时延与 buffer 占用率成比例增长” 的事实&#xff0c;所以今天我…

基于NE555制作雾化加湿器

基于NE555制作雾化加湿器 &#x1f33c;实物制作图&#xff1a;&#xff08;只焊接了2路&#xff0c;进行功能验证&#xff09; &#x1f4fa;演示效果&#xff1a; &#x1f341;原理图&#xff1a; &#x1f389;其他方案&#xff1a;基于专用加湿器芯片&#xff1a;富…

noVNC使用与介绍

noVNC使用与介绍报告 1. 概述 VNC&#xff08;Virtual Network Console&#xff0c;虚拟网络控制台&#xff09;是一种流行的远程桌面访问协议&#xff0c;它允许用户通过网络连接到远程计算机的图形界面。VNC协议的实现通常包括两个主要组件&#xff1a;服务器端&#xff08…

充满惊喜与欢乐的老友

在这个充满惊喜与欢笑的娱乐圈里&#xff0c;每一个不经意的可能成为网友热议的焦点&#xff0c;而《快乐老友记》的花絮&#xff0c;无疑为这个多彩的世界又添上了一抹亮丽的色彩。当“王栎鑫被路人认成张艺兴”这一话题如春风般拂过网络&#xff0c;不仅让两位才华横溢的艺人…

硬核科普:什么是网络准入控制系统|网络准入控制系统四大品牌介绍

网络准入控制系统&#xff08;Network Access Control, NAC&#xff09;是一种用于确保只有授权设备和用户才能接入网络的安全技术。 本文将介绍几种常用的网络准入控制系统&#xff0c;帮助您更好地了解如何选择适合您企业的NAC系统。 网络准入控制的重要性和作用 网络准入控…

Jenkins集成JDK、git、gitee、maven逐步实现自动拉取,自动部署,自动启动

1. jenkins集成JDK 成功登录Jenkins后&#xff0c;选择Manage Jenkins&#xff0c;选择Tools 集成JDK 2. jenkins集成git 因为Jenkins自动从git远程仓库拉取代码 首先要在Jenkins所在的linux服务器上安装git yum install -y git然后&#xff0c;实行集成JDK的第一步 配置g…