基于Spring Boot的多级缓存架构实现
基于Spring Boot的多级缓存架构实现
以下是一个基于Spring Boot的多级缓存架构实现示例
多级缓存架构实现方案
1. 依赖配置(pom.xml)
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency><groupId>com.github.ben-manes.caffeine</groupId><artifactId>caffeine</artifactId>
</dependency>
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
2. 缓存配置类
@Configuration
@EnableCaching
public class MultiLevelCacheConfig {// 一级缓存(本地缓存)@Beanpublic CacheManager caffeineCacheManager() {CaffeineCacheManager manager = new CaffeineCacheManager();manager.setCaffeine(Caffeine.newBuilder().maximumSize(1000).expireAfterWrite(30, TimeUnit.SECONDS)); // 本地缓存比Redis缓存更短return manager;}// 二级缓存(Redis缓存)@Beanpublic CacheManager redisCacheManager(RedisConnectionFactory factory) {RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofMinutes(5)).serializeValuesWith(SerializationPair.fromSerializer(RedisSerializer.json()));return RedisCacheManager.builder(factory).cacheDefaults(config).transactionAware().build();}// 组合缓存管理器@Bean@Primarypublic CacheManager multiLevelCacheManager(@Qualifier("caffeineCacheManager") CacheManager level1,@Qualifier("redisCacheManager") CacheManager level2) {return new MultiLevelCacheManager(level1, level2);}
}
3. 多级缓存管理器实现
public class MultiLevelCacheManager implements CacheManager {private final CacheManager level1; // 本地缓存private final CacheManager level2; // Redis缓存private final ConcurrentMap<String, Cache> cacheMap = new ConcurrentHashMap<>();public MultiLevelCacheManager(CacheManager level1, CacheManager level2) {this.level1 = level1;this.level2 = level2;}@Overridepublic Cache getCache(String name) {return cacheMap.computeIfAbsent(name, key -> new MultiLevelCache(level1.getCache(name), level2.getCache(name)));}@Overridepublic Collection<String> getCacheNames() {return Stream.concat(level1.getCacheNames().stream(),level2.getCacheNames().stream()).collect(Collectors.toSet());}// 多级缓存实现static class MultiLevelCache implements Cache {private final Cache level1;private final Cache level2;private final String name;public MultiLevelCache(Cache level1, Cache level2) {this.level1 = level1 != null ? level1 : new NoOpCache();this.level2 = level2 != null ? level2 : new NoOpCache();this.name = level1.getName() + ":" + level2.getName();}@Overridepublic String getName() {return name;}@Overridepublic Object getNativeCache() {return this;}@Overridepublic ValueWrapper get(Object key) {// 先查一级缓存ValueWrapper value = level1.get(key);if (value == null) {// 二级缓存查询value = level2.get(key);if (value != null) {// 回填一级缓存level1.put(key, value.get());}}return value;}@Overridepublic <T> T get(Object key, Class<T> type) {// 实现逻辑类似get方法T value = level1.get(key, type);if (value == null) {value = level2.get(key, type);if (value != null) {level1.put(key, value);}}return value;}@Overridepublic void put(Object key, Object value) {// 同时写入两级缓存level1.put(key, value);level2.put(key, value);}@Overridepublic void evict(Object key) {// 同时清除两级缓存level1.evict(key);level2.evict(key);}@Overridepublic void clear() {level1.clear();level2.clear();}}// 空缓存实现(容错)static class NoOpCache implements Cache {// 实现基础的Cache方法,返回空值}
}
4. 业务层使用
@Service
public class ProductService {@Cacheable(value = "products", key = "#id")public Product getProduct(Long id) {// 数据库查询逻辑return productRepository.findById(id).orElseThrow(() -> new NotFoundException("Product not found"));}@CacheEvict(value = "products", key = "#product.id")public void updateProduct(Product product) {productRepository.save(product);}
}
5. 配置说明(application.yml)
spring:cache:multi-level:level1:ttl: 30s # 本地缓存时间max-size: 1000level2:ttl: 5m # Redis缓存时间redis:host: redis-cluster.prodport: 6379timeout: 2000ms
关键实现要点
- 缓存层级策略
- 一致性保障
- 写操作:同时清除两级缓存(
@CacheEvict) - 读操作:二级缓存命中后自动回填一级缓存
- TTL策略:一级缓存TTL(30s) < 二级缓存TTL(5m)
- 性能优化
- 本地缓存:使用Caffeine高性能缓存库
- 异步回填:可扩展为异步加载(需自定义CacheLoader)
- 批量操作:支持@Cacheable的批量查询优化
扩展建议
- 缓存预热
@PostConstruct
public void preloadHotData() {// 加载热点数据到缓存hotProducts.forEach(product -> cacheManager.getCache("products").put(product.getId(), product));
}
- 监控集成
@Bean
public MeterRegistryCustomizer<MeterRegistry> cacheMetrics() {return registry -> {CaffeineCacheManager caffeine = context.getBean(CaffeineCacheManager.class);RedisCacheManager redis = context.getBean(RedisCacheManager.class);// 注册Caffeine监控CacheMetrics.monitor(registry, caffeine, "level1");// 注册Redis监控CacheMetrics.monitor(registry, redis, "level2");};
}
- 防雪崩策略
// 在MultiLevelCache.get方法中添加
ValueWrapper get(Object key) {try {// 添加分布式锁检查if (lockManager.tryLock(key)) {// 实际查询逻辑}} finally {lockManager.unlock(key);}
}
相关文章:
基于Spring Boot的多级缓存架构实现
基于Spring Boot的多级缓存架构实现 以下是一个基于Spring Boot的多级缓存架构实现示例 多级缓存架构实现方案 1. 依赖配置(pom.xml) <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-star…...
Git与GitHub:理解两者差异及其关系
目录 Git与GitHub:理解两者差异及其关系Git:分布式版本控制系统概述主要特点 GitHub:基于Web的托管服务概述主要特点 Git和GitHub如何互补关系现代开发工作流 结论 Git与GitHub:理解两者差异及其关系 Git:分布式版本控…...
ALG(Alloy+Loki+Grafana)轻量级日志系统
ALG(AlloyLokiGrafana)轻量级日志系统 前提要求 GrafanaMinioNginxPrometheus Grafana日志收集系统旧版是PLG(ProtailLokiGrafana), Protail收集日志, Loki存储, Grafana展示, 后续的Protail不维护了, Grafana推出了Alloy代替Pritial, 除了收集日志外, 还集成管理Prometheus各种…...
【漫话机器学习系列】121.偏导数(Partial Derivative)
偏导数(Partial Derivative)详解 1. 引言 在数学分析、机器学习、物理学和工程学中,我们经常会遇到多个变量的函数。这些函数的输出不仅取决于一个变量,而是由多个变量共同决定的。那么,当其中某一个变量发生变化时&…...
Deepseek可以通过多种方式帮助CAD加速工作
自动化操作:通过Deepseek的AI能力,可以编写脚本来自动化重复性任务。例如,使用Python脚本调用Deepseek API,在CAD中实现自动化操作。 插件开发:结合Deepseek进行二次开发,可以创建自定义的CAD插件。例如&a…...
【工具使用】IDEA 社区版如何创建 Spring Boot 项目(详细教程)
IDEA 社区版如何创建 Spring Boot 项目(详细教程) Spring Boot 以其简洁、高效的特性,成为 Java 开发的主流框架之一。虽然 IntelliJ IDEA 专业版提供了Spring Boot 项目向导,但 社区版(Community Edition)…...
QT中串口打开按钮如何点击打开后又能点击关闭
前言: if (!portOpen) { // 打开串口 if (!sp18Controller->initializePort("COM5", 38400)) { QMessageBox::critical(this, "Error", "Failed to open serial port."); return; } ui->btnOpenPort_2->setText("Close…...
【AI深度学习基础】PyTorch初探
引言 PyTorch 是由 Facebook 开源的深度学习框架,专门针对 GPU 加速的深度神经网络编程,它的核心概念包括张量(Tensor)、计算图和自动求导机制。PyTorch作为Facebook开源的深度学习框架,凭借其动态计算图和直观的API设…...
springboot011基于springboot的课程作业管理系统(源码+包运行+LW+技术指导)
项目描述 临近学期结束,还是毕业设计,你还在做java程序网络编程,期末作业,老师的作业要求觉得难了吗?不知道毕业设计该怎么办?网页功能的数量是否太多?没有合适的类型或系统?等等,你想解决的问题,今天…...
快速从C过度C++(一):namespace,C++的输入和输出,缺省参数,函数重载
📝前言: 本文章适合有一定C语言编程基础的读者浏览,主要介绍从C语言到C过度,我们首先要掌握的一些基础知识,以便于我们快速进入C的学习,为后面的学习打下基础。 这篇文章的主要内容有: 1&#x…...
PostgreSQL时间计算大全:从时间差到时区转换(保姆级教程)
一、时间计算的三大核心场景 当你遇到这些需求时,本文就是你的救星🌟: 倒计时功能:计算活动剩余天数 用户行为分析:统计操作间隔时间 跨国系统:多时区时间统一管理 报表生成:自动计算同比/环…...
laravel es 相关代码 ElasticSearch
来源: github <?phpnamespace App\Http\Controllers;use Elastic\Elasticsearch\ClientBuilder; use Illuminate\Support\Facades\DB;class ElasticSearch extends Controller {public $client null;public function __construct(){$this->client ClientB…...
题目 3220 ⭐因数计数⭐【数理基础】蓝桥杯2024年第十五届省赛
小蓝随手写出了含有 n n n 个正整数的数组 a 1 , a 2 , ⋅ ⋅ ⋅ , a n {a_1, a_2, , a_n} a1,a2,⋅⋅⋅,an ,他发现可以轻松地算出有多少个有序二元组 ( i , j ) (i, j) (i,j) 满足 a j a_j aj 是 a i a_i ai 的一个因数。因此他定义一个整数对 …...
【Java代码审计 | 第十一篇】SSRF漏洞成因及防范
未经许可,不得转载。 文章目录 SSRF漏洞成因Java中发送HTTP请求的函数1、HttpURLConnection2、HttpClient(Java 11)3、第三方库Request库漏洞示例OkHttpClient漏洞示例HttpClients漏洞示例 漏洞代码示例防范标准代码 SSRF SSRF(S…...
RabbitMQ高级特性--消息确认机制
目录 一、消息确认 1.消息确认机制 2.手动确认方法 二、代码示例 1. AcknowledgeMode.NONE 1.1 配置文件 1.2 生产者 1.3 消费者 1.4 运行程序 2.AcknowledgeMode.AUTO 3.AcknowledgeMode.MANUAL 一、消息确认 1.消息确认机制 生产者发送消息之后,到达消…...
C++复试笔记(一)
Setw 是C中用于设置输出字段宽度的函数。当使用 setw(3) 时,它会设置紧接着的输出字段的最小宽度为3个字符。如果字段内容长度小于3,则会在左侧填充空格以达到指定宽度;如果内容长度大于或等于3,则全部内容将被输出,…...
K8s 1.27.1 实战系列(四)验证集群及应用部署测试
一、验证集群可用性 1、检查节点 kubectl get nodes ------------------------------------------------------ NAME STATUS ROLES AGE VERSION k8s-master Ready control-plane 3h48m v1.27.1 k8s-node1 Ready <none> …...
基于Spring Boot的健美操评分管理系统设计与实现(LW+源码+讲解)
专注于大学生项目实战开发,讲解,毕业答疑辅导,欢迎高校老师/同行前辈交流合作✌。 技术范围:SpringBoot、Vue、SSM、HLMT、小程序、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容:…...
H5页面在移动端自动横屏
首先需要再head标签添加这样一段代码 <meta name="viewport" content="width=device-width,height=device-width,initial-scale=1.0,user-scalable=no">因为需求是为了满足WEB端和手机端都可以查看整体效果 但由于UI没有设计移动端的样式 所以我想说…...
【从0到1搞懂大模型】神经网络的实现:数据策略、模型调优与评估体系(3)
一、数据集的划分 (1)按一定比例划分为训练集和测试集 我们通常取8-2、7-3、6-4、5-5比例切分,直接将数据随机划分为训练集和测试集,然后使用训练集来生成模型,再用测试集来测试模型的正确率和误差,以验证…...
生成xcframework
打包 XCFramework 的方法 XCFramework 是苹果推出的一种多平台二进制分发格式,可以包含多个架构和平台的代码。打包 XCFramework 通常用于分发库或框架。 使用 Xcode 命令行工具打包 通过 xcodebuild 命令可以打包 XCFramework。确保项目已经配置好需要支持的平台…...
【网络】每天掌握一个Linux命令 - iftop
在Linux系统中,iftop是网络管理的得力助手,能实时监控网络流量、连接情况等,帮助排查网络异常。接下来从多方面详细介绍它。 目录 【网络】每天掌握一个Linux命令 - iftop工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景…...
C++初阶-list的底层
目录 1.std::list实现的所有代码 2.list的简单介绍 2.1实现list的类 2.2_list_iterator的实现 2.2.1_list_iterator实现的原因和好处 2.2.2_list_iterator实现 2.3_list_node的实现 2.3.1. 避免递归的模板依赖 2.3.2. 内存布局一致性 2.3.3. 类型安全的替代方案 2.3.…...
智慧医疗能源事业线深度画像分析(上)
引言 医疗行业作为现代社会的关键基础设施,其能源消耗与环境影响正日益受到关注。随着全球"双碳"目标的推进和可持续发展理念的深入,智慧医疗能源事业线应运而生,致力于通过创新技术与管理方案,重构医疗领域的能源使用模式。这一事业线融合了能源管理、可持续发…...
树莓派超全系列教程文档--(62)使用rpicam-app通过网络流式传输视频
使用rpicam-app通过网络流式传输视频 使用 rpicam-app 通过网络流式传输视频UDPTCPRTSPlibavGStreamerRTPlibcamerasrc GStreamer 元素 文章来源: http://raspberry.dns8844.cn/documentation 原文网址 使用 rpicam-app 通过网络流式传输视频 本节介绍来自 rpica…...
Oracle查询表空间大小
1 查询数据库中所有的表空间以及表空间所占空间的大小 SELECTtablespace_name,sum( bytes ) / 1024 / 1024 FROMdba_data_files GROUP BYtablespace_name; 2 Oracle查询表空间大小及每个表所占空间的大小 SELECTtablespace_name,file_id,file_name,round( bytes / ( 1024 …...
Cesium1.95中高性能加载1500个点
一、基本方式: 图标使用.png比.svg性能要好 <template><div id"cesiumContainer"></div><div class"toolbar"><button id"resetButton">重新生成点</button><span id"countDisplay&qu…...
ssc377d修改flash分区大小
1、flash的分区默认分配16M、 / # df -h Filesystem Size Used Available Use% Mounted on /dev/root 1.9M 1.9M 0 100% / /dev/mtdblock4 3.0M...
c++ 面试题(1)-----深度优先搜索(DFS)实现
操作系统:ubuntu22.04 IDE:Visual Studio Code 编程语言:C11 题目描述 地上有一个 m 行 n 列的方格,从坐标 [0,0] 起始。一个机器人可以从某一格移动到上下左右四个格子,但不能进入行坐标和列坐标的数位之和大于 k 的格子。 例…...
Java - Mysql数据类型对应
Mysql数据类型java数据类型备注整型INT/INTEGERint / java.lang.Integer–BIGINTlong/java.lang.Long–––浮点型FLOATfloat/java.lang.FloatDOUBLEdouble/java.lang.Double–DECIMAL/NUMERICjava.math.BigDecimal字符串型CHARjava.lang.String固定长度字符串VARCHARjava.lang…...
