当前位置: 首页 > news >正文

基于Spring Boot的多级缓存系统设计

在构建大规模应用时,缓存系统是提高性能的关键因素之一。为了更有效地利用缓存,我们可以设计一个基于Spring Boot的多级缓存系统,结合本地内存缓存(如Caffeine)和分布式缓存(如Redis)。以下是一个简单的多级缓存系统的设计概要:

1. 选择缓存框架

在Spring Boot中,我们可以选择合适的缓存框架,比如Ehcache、Redis、Caffeine等。可以通过在pom.xml中引入相应的依赖来集成这些框架。

2. 配置缓存

在application.properties或application.yml中配置缓存的相关属性,如缓存类型、大小、过期时间等。

3. 定义缓存管理类

创建一个缓存管理类,用于配置多级缓存,指定各级缓存的顺序和策略。

package com.nbsaas.boot.config;import com.github.benmanes.caffeine.cache.CaffeineSpec;
import com.nbsaas.boot.cache.MultiLevelCacheManager;
import org.springframework.cache.CacheManager;
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 org.springframework.context.annotation.Primary;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;import java.time.Duration;@Configuration
@EnableCaching
public class CacheConfig {@Primary@Order(Ordered.HIGHEST_PRECEDENCE)@Beanpublic CacheManager cacheManager(CaffeineCacheManager caffeineCacheManager,RedisCacheManager redisCacheManager) {MultiLevelCacheManager multiLevelCacheManager = new MultiLevelCacheManager();multiLevelCacheManager.addCache(caffeineCacheManager);multiLevelCacheManager.addCache(redisCacheManager);return multiLevelCacheManager;}@Beanpublic CaffeineCacheManager caffeineCacheManager() {// 配置Caffeine缓存CaffeineCacheManager cacheManager = new CaffeineCacheManager("caffeineCache","yourCacheName");cacheManager.setCaffeineSpec(caffeineSpec());return cacheManager;}@Order(Ordered.LOWEST_PRECEDENCE)@Beanpublic RedisCacheManager redisCacheManager(RedisConnectionFactory factory) {RedisSerializer<String> redisSerializer = new StringRedisSerializer();GenericJackson2JsonRedisSerializer jackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer();// 配置序列化(解决乱码的问题),过期时间600秒RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofSeconds(600)).serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer)).serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer)).disableCachingNullValues();return RedisCacheManager.builder(factory).cacheDefaults(config).build();}private CaffeineSpec caffeineSpec() {// 配置Caffeine缓存规格return CaffeineSpec.parse("maximumSize=100");}
}

4. 实现缓存管理器和缓存

实现MultiLevelCacheManager类和MultiLevelCache类,用于管理和协调多个缓存层次。


package com.nbsaas.boot.cache;import org.springframework.cache.Cache;import java.util.ArrayList;
import java.util.Collection;
import java.util.concurrent.Callable;public class MultiLevelCache implements Cache {private final ArrayList<Cache> caches = new ArrayList<>();public void addCache(Cache cache) {caches.add(cache);}@Overridepublic String getName() {return "multiLevelCache";}@Overridepublic Object getNativeCache() {return this;}@Overridepublic ValueWrapper get(Object key) {for (Cache cache : caches) {ValueWrapper wrapper = cache.get(key);if (wrapper != null) {return wrapper;}}return null;}@Overridepublic <T> T get(Object key, Class<T> type) {ValueWrapper wrapper = get(key);return (wrapper != null) ? (T) wrapper.get() : null;}@Overridepublic <T> T get(Object key, Callable<T> valueLoader) {ValueWrapper wrapper = get(key);T obj= (wrapper != null) ? (T) wrapper.get() : null;return obj;}@Overridepublic void put(Object key, Object value) {for (Cache cache : caches) {cache.put(key, value);}}@Overridepublic ValueWrapper putIfAbsent(Object key, Object value) {ValueWrapper wrapper = get(key);if (wrapper == null) {put(key, value);return null;}return wrapper;}@Overridepublic void evict(Object key) {for (Cache cache : caches) {cache.evict(key);}}@Overridepublic boolean evictIfPresent(Object key) {return Cache.super.evictIfPresent(key);}@Overridepublic void clear() {for (Cache cache : caches) {cache.clear();}}@Overridepublic boolean invalidate() {boolean result=true;for (Cache cache : caches) {result= cache.invalidate();}return result;}
}

package com.nbsaas.boot.cache;import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;import java.util.ArrayList;
import java.util.Collection;public class MultiLevelCacheManager implements CacheManager {private final ArrayList<CacheManager> cacheManagers = new ArrayList<>();public static final int REDIS_CACHE_EXPIRATION = 600; // Redis缓存过期时间(秒)public void addCache(CacheManager cacheManager) {cacheManagers.add(cacheManager);}@Overridepublic Cache getCache(String name) {MultiLevelCache multiLevelCache = new MultiLevelCache();for (CacheManager cacheManager : cacheManagers) {Cache cache = cacheManager.getCache(name);if (cache != null) {multiLevelCache.addCache(cache);}}return multiLevelCache;}@Overridepublic Collection<String> getCacheNames() {Collection<String> cacheNames = new ArrayList<>();for (CacheManager cacheManager : cacheManagers) {cacheNames.addAll(cacheManager.getCacheNames());}return cacheNames;}
}

5. 使用缓存

在Service层或方法上使用@Cacheable、@CachePut、@CacheEvict等注解来标记需要缓存的方法。

@Service
public class MyService {@Cacheable(value = "caffeineCache", key = "#id")public String getCachedData(String id) {// 查询数据库或其他业务逻辑return "Cached Data for " + id;}
}

通过以上步骤,我们成功建立了一个基于Spring Boot的多级缓存系统。这个设计支持在本地内存和分布式缓存之间实现多级缓存,从而更好地满足不同场景下的性能需求。在实际应用中,可以根据具体需求调整缓存的层次和配置,以达到最佳性能和资源利用率。

相关文章:

基于Spring Boot的多级缓存系统设计

在构建大规模应用时&#xff0c;缓存系统是提高性能的关键因素之一。为了更有效地利用缓存&#xff0c;我们可以设计一个基于Spring Boot的多级缓存系统&#xff0c;结合本地内存缓存&#xff08;如Caffeine&#xff09;和分布式缓存&#xff08;如Redis&#xff09;。以下是一…...

k8s-配置与存储-配置管理

文章目录 一、配置存储1.1 ConfigMap1.1.1.基于文件夹的创建方式1.1.2指定文件的创建方式1.1.3 配置文件创建configmap 1.2 Secret1.2.1Secret的应用与Docker仓库 Secret设置1. Kubernetes 中的 Secrets&#xff1a;创建 Secret 示例&#xff1a;将 Secret 挂载到 Pod 中的示例…...

c语言实现bellman-ford算法

下面是使用C语言实现Bellman-Ford算法的示例代码。Bellman-Ford算法用于在带权重的图中找到从单个源点到所有其他顶点的最短路径,它也能处理图中包含负权重边的情况。 #include <stdio.h> #include <stdlib.h> #include <limits.h>// 定义边的结构 struct …...

socket与rpc的区别

如今的游戏开发&#xff0c;不搞个跨服玩法都不好意思说在做游戏了&#xff08;当然&#xff0c;也跟游戏类型有关&#xff0c;一些轻度休闲游戏可以排除在外&#xff09;。跨服玩法的设计&#xff0c;可以进一步激发玩家追求高战力的虚荣心&#xff0c;也可以汇聚玩家数量&…...

10、内网安全-横向移动域控提权NetLogonADCSPACKDC永恒之蓝

用途&#xff1a;个人学习笔记&#xff0c;有所借鉴&#xff0c;欢迎指正&#xff01; 背景&#xff1a; 主要针对内网主机中的 域控提权漏洞&#xff0c;包含漏洞探针和漏洞复现利用。 1、横向移动-系统漏洞-CVE-2017-0146&#xff08;ms17-010&#xff0c;永恒之蓝&#xff0…...

代码随想录算法训练营第三八天 | 动态规划

目录 动态规划基础斐波那契数爬楼梯使用最小花费爬楼梯 LeetCode 509. 斐波那契数 LeetCode 70. 爬楼梯 LeetCode 746. 使用最小花费爬楼梯 动态规划基础 Dynamic Programming (DP) 如果某一问题有很多重叠子问题&#xff0c;使用动态规划是最有效的。 动态规划中每一个状态…...

【ubuntu2004安装N卡驱动】

软硬件环境 硬件&#xff1a;联想notebook16&#xff0c;显卡4060laptop 软件&#xff1a; ubuntu20.04 驱动安装成功的版本&#xff1a;NVIDIA-Linux-x86_64-535.146.02.run 使用默认的驱动安装&#xff0c;没用原因如下 让手动安装。 手动安装 环境准备&#xff1a; sudo …...

使用 Docker 安装 Kibana 8.4.3

使用 Docker 安装 Kibana 8.4.3 一. 安装启动 Kibana 8.4.3二. 简单使用2.1 向 Elasticsearch 发送请求2.2 搜索2.3 整体页面 前言 这是我在这个网站整理的笔记,有错误的地方请指出&#xff0c;关注我&#xff0c;接下来还会持续更新。 作者&#xff1a;神的孩子都在歌唱 安装k…...

基于python社交网络大数据分析系统的设计与实现

项目&#xff1a;基于python社交网络大数据分析系统的设计与实现 摘 要 社交网络大数据分析系统是一种能自动从网络上收集信息的工具&#xff0c;可根据用户的需求定向采集特定数据信息的工具&#xff0c;本项目通过研究爬取微博网来实现社交网络大数据分析系统功能。对于采集…...

【设计模式】23种设计模式笔记

设计模式分类 模板方法模式 核心就是设计一个部分抽象类。 这个类具有少量具体的方法&#xff0c;和大量抽象的方法&#xff0c;具体的方法是为外界提供服务的点&#xff0c;具体方法中定义了抽象方法的执行序列 装饰器模式 现在有一个对象A&#xff0c;希望A的a方法被修饰 …...

编程笔记 Golang基础 009 标识符和关键字

编程笔记 Golang基础 009 标识符和关键字 一、标识符二、标识符分类&#xff08;一&#xff09;空白标识符&#xff08;又称下划线 _&#xff09;&#xff08;二&#xff09;预声明标识符&#xff08;三&#xff09;唯一标识符&#xff08;四&#xff09;导出标识符 三、关键字…...

vue3中mockjs模拟获取数据

开发项目的时候&#xff0c;如果后端接口没有出来&#xff0c;前端工程师也不必非得等接口出来才进行下步开发。可以使用mock.js来模拟接口数据&#xff0c;以下就是使用vue3设置hook函数来封装axios请求&#xff0c;配合mock.js来实现的代码&#xff0c;mock的官网 Mock.js 一…...

element ui 添加自定义方法

今天在修改 el-table 源码过程中遇到一个头大的问题&#xff0c;原本修改编译后&#xff0c;将 element的子目录lib下的文件复制到项目的响应目录里就可以了&#xff0c;但是&#xff0c;这次不知为何&#xff0c;编译老是出问题&#xff0c;实在没有办法&#xff0c;我就直接修…...

Hive UDF

当Hive提供的内置函数不能满足查询需求时&#xff0c;用户可以根据自己业务编写自定义函数&#xff08;User Defined Functions, UDF), 然后在HiveQL中调用。 例如有这样一个需求&#xff1a;为了保护用户隐私&#xff0c;当查询数据的时候&#xff0c;需要将用户手机号的中间…...

python Opencv 中绘制图

目录 一:绘制直线 二:绘制矩形 三:绘制圆形 四:绘制椭圆...

imazing软件安全吗?2024中文永久免费许可证

以下是iMazing更多的使用场景描述&#xff1a; iMazing3Mac-最新绿色安装包下载如下&#xff1a; https://wm.makeding.com/iclk/?zoneid49816 iMazing3Win-最新绿色安装包下载如下&#xff1a; https://wm.makeding.com/iclk/?zoneid49817 1. 数据迁移 当你换新的iOS设…...

JavaScript:防抖与节流

文章目录 防抖(Debounce)节流 (Throttle) 在JavaScript中&#xff0c;防抖&#xff08;debounce&#xff09;和节流&#xff08;throttle&#xff09;是两种优化函数调用频率的策略&#xff0c;它们主要用于限制频繁触发的事件回调函数执行次数&#xff0c;以防止过多不必要的计…...

在Win系统部署WampServer并实现公网访问本地服务【内网穿透】

目录 推荐 前言 1.WampServer下载安装 2.WampServer启动 3.安装cpolar内网穿透 3.1 注册账号 3.2 下载cpolar客户端 3.3 登录cpolar web ui管理界面 3.4 创建公网地址 4.固定公网地址访问 推荐 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0…...

面试经典150题——单词规律

"Dont wait. The time will never be just right." - Napoleon Hill 1. 题目描述 2. 题目分析与解析 首先还是得把题目先读懂&#xff0c;我们直接来看看示例&#xff1a; 根据上面的示例&#xff0c;我们可以看出pattern其实就是表示单词出现的规律&#xff0c;每…...

RK3568平台开发系列讲解(Linux系统篇)container_of

🚀返回专栏总目录 文章目录 一、理解宏container_of二、使用案例沉淀、分享、成长,让自己和他人都能有所收获!😄 一、理解宏container_of 在代码中管理多个数据结构时,几乎总是需要将一个结构嵌入另一个结构中,并随时检索它们,而不关心有关内存偏移或边界的问题。假设…...

关于nvm与node.js

1 安装nvm 安装过程中手动修改 nvm的安装路径&#xff0c; 以及修改 通过nvm安装node后正在使用的node的存放目录【这句话可能难以理解&#xff0c;但接着往下看你就了然了】 2 修改nvm中settings.txt文件配置 nvm安装成功后&#xff0c;通常在该文件中会出现以下配置&…...

Go 语言接口详解

Go 语言接口详解 核心概念 接口定义 在 Go 语言中&#xff0c;接口是一种抽象类型&#xff0c;它定义了一组方法的集合&#xff1a; // 定义接口 type Shape interface {Area() float64Perimeter() float64 } 接口实现 Go 接口的实现是隐式的&#xff1a; // 矩形结构体…...

生成 Git SSH 证书

&#x1f511; 1. ​​生成 SSH 密钥对​​ 在终端&#xff08;Windows 使用 Git Bash&#xff0c;Mac/Linux 使用 Terminal&#xff09;执行命令&#xff1a; ssh-keygen -t rsa -b 4096 -C "your_emailexample.com" ​​参数说明​​&#xff1a; -t rsa&#x…...

PHP 8.5 即将发布:管道操作符、强力调试

前不久&#xff0c;PHP宣布了即将在 2025 年 11 月 20 日 正式发布的 PHP 8.5&#xff01;作为 PHP 语言的又一次重要迭代&#xff0c;PHP 8.5 承诺带来一系列旨在提升代码可读性、健壮性以及开发者效率的改进。而更令人兴奋的是&#xff0c;借助强大的本地开发环境 ServBay&am…...

Java求职者面试指南:Spring、Spring Boot、Spring MVC与MyBatis技术解析

Java求职者面试指南&#xff1a;Spring、Spring Boot、Spring MVC与MyBatis技术解析 一、第一轮基础概念问题 1. Spring框架的核心容器是什么&#xff1f;它的作用是什么&#xff1f; Spring框架的核心容器是IoC&#xff08;控制反转&#xff09;容器。它的主要作用是管理对…...

网页端 js 读取发票里的二维码信息(图片和PDF格式)

起因 为了实现在报销流程中&#xff0c;发票不能重用的限制&#xff0c;发票上传后&#xff0c;希望能读出发票号&#xff0c;并记录发票号已用&#xff0c;下次不再可用于报销。 基于上面的需求&#xff0c;研究了OCR 的方式和读PDF的方式&#xff0c;实际是可行的&#xff…...

FTXUI::Dom 模块

DOM 模块定义了分层的 FTXUI::Element 树&#xff0c;可用于构建复杂的终端界面&#xff0c;支持响应终端尺寸变化。 namespace ftxui {...// 定义文档 定义布局盒子 Element document vbox({// 设置文本 设置加粗 设置文本颜色text("The window") | bold | color(…...

接口 RESTful 中的超媒体:REST 架构的灵魂驱动

在 RESTful 架构中&#xff0c;** 超媒体&#xff08;Hypermedia&#xff09;** 是一个核心概念&#xff0c;它体现了 REST 的 “表述性状态转移&#xff08;Representational State Transfer&#xff09;” 的本质&#xff0c;也是区分 “真 RESTful API” 与 “伪 RESTful AP…...

【大厂机试题解法笔记】矩阵匹配

题目 从一个 N * M&#xff08;N ≤ M&#xff09;的矩阵中选出 N 个数&#xff0c;任意两个数字不能在同一行或同一列&#xff0c;求选出来的 N 个数中第 K 大的数字的最小值是多少。 输入描述 输入矩阵要求&#xff1a;1 ≤ K ≤ N ≤ M ≤ 150 输入格式 N M K N*M矩阵 输…...

篇章一 论坛系统——前置知识

目录 1.软件开发 1.1 软件的生命周期 1.2 面向对象 1.3 CS、BS架构 1.CS架构​编辑 2.BS架构 1.4 软件需求 1.需求分类 2.需求获取 1.5 需求分析 1. 工作内容 1.6 面向对象分析 1.OOA的任务 2.统一建模语言UML 3. 用例模型 3.1 用例图的元素 3.2 建立用例模型 …...