基于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比例切分,直接将数据随机划分为训练集和测试集,然后使用训练集来生成模型,再用测试集来测试模型的正确率和误差,以验证…...

从0到1入门RabbitMQ
一、同步调用 优势:时效性强,等待到结果后才返回 缺点: 拓展性差性能下降级联失败问题 二、异步调用 优势: 耦合度低,拓展性强异步调用,无需等待,性能好故障隔离,下游服务故障不影响…...

MySQL数据库复杂的增删改查操作
在前面的文章中,我们主要学习了数据库的基础知识以及基本的增删改查的操作。接下去将以一个比较实际的公司数据库为例子,进行讲解一些较为复杂且现时需求的例子。 基础知识: 一文清晰梳理Mysql 数据库基础知识_字段变动如何梳理清楚-CSDN博…...

点云软件VeloView开发环境搭建与编译
官方编译说明 LidarView / LidarView-Superbuild GitLab 我的编译过程: 安装vs2019,windows sdk,qt5.14.2(没安装到5.15.7),git,cmake3.31,python3.7.9,ninja下载放到…...

本地YARN集群部署
请先完成HDFS的前置部署,部署方式可查看:本地部署HDFS集群https://blog.csdn.net/m0_73641796/article/details/145998092?spm1001.2014.3001.5502 部署说明 组件配置文件启动进程备注Hadoop HDFS需修改 需启动: NameNode作为主节点 DataNode作为从节点 Secondary…...

STM32常见外设的驱动示例和代码解析
以下是针对STM32常见外设的驱动示例和代码解析,基于HAL库实现,适用于大多数STM32系列(如F1/F4/H7等),可根据具体型号调整引脚和时钟配置。 1. GPIO驱动 应用场景:控制LED、按键检测、继电器开关等。 示例代码: // 初始化LED(推挽输出) void LED_Init(void) {GPIO_In…...

使用数据库和缓存的时候,是如何解决数据不一致的问题的?
1.缓存更新策略 1.1. 缓存旁路模式(Cache Aside) 在应用里负责管理缓存,读取时先查缓存,如果命中了则返回缓存,如果未命中就查询数据库,然后返回缓存,返回缓存的同时把数据给写入缓存中。更新…...

VS Code C++ 开发环境配置
VS Code 是当前非常流行的开发工具. 本文讲述如何配置 VS Code 作为 C开发环境. 本文将按照如下步骤来介绍如何配置 VS Code 作为 C开发环境. 安装编译器安装插件配置工作区 第一个步骤的具体操作会因为系统不同或者方案不同而有不同的选择. 环境要求 首先需要立即 VS Code…...

使用OpenCV和MediaPipe库——实现人体姿态检测
目录 准备工作如何在Windows系统中安装OpenCV和MediaPipe库? 安装Python 安装OpenCV 安装MediaPipe 验证安装 代码逻辑 整体代码 效果展示 准备工作如何在Windows系统中安装OpenCV和MediaPipe库? 安装Python 可以通过命令行运行python --versio…...

JWT的学习
1、HTTP无状态及解决方案 HTTP一种是无状态的协议,每次请求都是一次独立的请求,一次交互之后就是陌生人。 以CSDN为例,先登录一次,然后浏览器退出,这个时候在进入CSDN,按理说服务器是不知道你已经登陆了&…...

elasticsearch是哪家的
Elasticsearch:数据搜索与分析的领航者 在当今这个信息爆炸的时代,快速且准确地处理海量数据成为了众多企业和组织追求的目标。而Elasticsearch正是在这个背景下脱颖而出的一款强大的开源搜索引擎。它是由位于美国加利福尼亚州的Elastic公司所开发和维护…...