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

精通 Spring Cache + Redis:避坑指南与最佳实践

Spring Cache 以其优雅的注解方式,极大地简化了 Java 应用中缓存逻辑的实现。结合高性能的内存数据库 Redis,我们可以轻松构建出响应迅速、扩展性强的应用程序。然而,在享受便捷的同时,一些常见的“坑”和被忽视的最佳实践可能会悄悄地影响你的应用性能和稳定性。

本文将深入探讨在使用 Spring Cache 结合 Redis 时最需要注意的几个关键点,并提供切实可行的避坑指南和最佳实践,助你用好

1. 序列化陷阱:告别乱码,拥抱 JSON

问题: 当你兴冲冲地配置好 Spring Cache 和 Redis,并缓存了一个 Java 对象后,去 Redis 里查看,可能会看到一堆类似 ¬í\x00\x05sr\x00\x0Ecom.example...​ 的乱码。这是因为 Spring Boot 默认使用了 JDK 的序列化机制 (JdkSerializationRedisSerializer​)。

痛点:

  • 可读性为零: 无法直观判断缓存内容,调试极其困难。
  • 跨语言障碍: Java 特有格式,其他语言服务无法读取。
  • 版本兼容性差: 类结构变更可能导致反序列化失败。
  • 潜在安全风险: 反序列化漏洞不容忽视。

最佳实践:使用 JSON 序列化 (Jackson)

JSON 格式是文本格式,具有良好的可读性和跨语言通用性。通过配置 Jackson2JsonRedisSerializer​,你可以让缓存在 Redis 中的数据变得清晰可见,例如 {"id":123,"name":"Alice","email":"alice@example.com"}​。

如何配置? 创建一个 RedisCacheConfiguration​ Bean:

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.StringRedisSerializer;import java.time.Duration;@Configuration
@EnableCaching // 不要忘记开启缓存
public class CacheConfig {@Beanpublic RedisCacheManager cacheManager(RedisConnectionFactory connectionFactory) {// 配置 JSON 序列化器Jackson2JsonRedisSerializer<Object> jacksonSerializer = createJacksonSerializer();// 默认缓存配置:键用 String 序列化,值用 JSON 序列化,默认 TTL 1 小时RedisCacheConfiguration defaultCacheConfig = RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofHours(1)) // 设置默认 TTL.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer())).serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jacksonSerializer));// 可以为特定的 Cache Name 配置不同的 TTL 等// Map<String, RedisCacheConfiguration> cacheConfigurations = new HashMap<>();// cacheConfigurations.put("users", defaultCacheConfig.entryTtl(Duration.ofMinutes(30)));// cacheConfigurations.put("products", defaultCacheConfig.entryTtl(Duration.ofDays(1)));return RedisCacheManager.builder(connectionFactory).cacheDefaults(defaultCacheConfig)// .withInitialCacheConfigurations(cacheConfigurations) // 启用特定配置.build();}private Jackson2JsonRedisSerializer<Object> createJacksonSerializer() {ObjectMapper objectMapper = new ObjectMapper();// 指定要序列化的域、getter/setter 以及修饰符范围,ANY 是包括 private 和 publicobjectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);// 指定序列化输入的类型,类必须是非 final 修饰的。final 修饰的类,比如 String, Integer 等会抛出异常objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL);// 解决 Jackson2 无法反序列化 LocalDateTime 的问题objectMapper.registerModule(new JavaTimeModule());return new Jackson2JsonRedisSerializer<>(objectMapper, Object.class);}
}

关键: 使用 JSON 序列化能显著提升开发和调试效率,强烈推荐!

2. Key 的艺术:规范命名,动态生成

问题: 缓存的 Key 设计混乱,或者过于简单,可能导致:

  • Key 冲突: 不同业务数据使用了相同的 Key,导致缓存覆盖或读取错误。
  • 难以理解和管理: 无法通过 Key 快速定位对应的业务数据。
  • 批量清除困难: 无法按模块或业务维度精确清理缓存。

最佳实践:规范化、层级化、动态化

  • 规范格式: 推荐使用 :​ 分隔的层级结构,例如 模块名:业务名:唯一标识符​。如 user:info:123​ 或 product:detail:sku1001​。
  • 利用 SpEL: Spring Cache 的 key​ 属性支持强大的 SpEL (Spring Expression Language),可以动态地根据方法参数生成 Key。
@Service
public class UserServiceImpl implements UserService {// 使用 SpEL 引用方法参数 id,并结合固定前缀@Cacheable(value = "user:info", key = "#id")public User getUserById(Long id) {// ... 查询数据库 ...return user;}// 使用 SpEL 引用对象参数的属性@CachePut(value = "user:info", key = "#user.id")public User updateUser(User user) {// ... 更新数据库 ...return user;}// 引用第一个参数 (p0) 和第二个参数的 email 属性@Cacheable(value = "user:auth", key = "#p0 + ':' + #p1.email")public String getUserToken(Long userId, LoginRequest request) {// ... 生成 Token ...return token;}@CacheEvict(value = "user:info", key = "#id")public void deleteUser(Long id) {// ... 删除数据库 ...}
}

关键: 设计良好、一致的 Key 命名策略是高效使用缓存的基础。

3. TTL 的守护:设置过期时间,防止内存溢出

问题: 不设置缓存过期时间 (Time-To-Live, TTL),数据将永久存储在 Redis 中,直到手动删除或 Redis 内存耗尽。这会导致:

  • 内存溢出风险: Redis 内存持续增长,最终可能导致服务崩溃。
  • 数据不一致: 数据库数据已更新,但缓存仍然是旧数据(脏数据)。

最佳实践:合理配置 TTL

  • 全局默认 TTL: 在 RedisCacheConfiguration​ 中设置一个全局的默认过期时间 (entryTtl​),作为基础保障。 (见上面配置示例)
  • 特定 Cache Name 的 TTL: 可以为不同的 cacheNames​ (通过 @Cacheable​ 的 value​ 或 cacheNames​ 属性指定) 配置不同的 TTL。例如,用户会话缓存可能只需要 30 分钟,而商品信息缓存可以设置为 1 天。 (见上面配置示例中的注释部分)
  • 评估数据变更频率: TTL 的设置需要权衡:TTL 太短,缓存命中率低;TTL 太长,数据一致性风险高。需要根据业务数据的实际更新频率来决定。

关键: 永远不要忘记为你的缓存设置一个合理的过期时间!

4. 事务的纠缠:@Transactional​ 与缓存注解的顺序迷思

问题: 当 @CachePut​ 或 @CacheEvict​ 与 @Transactional​ 用在同一个方法上时,可能会出现问题。因为 Spring Cache 的 AOP 拦截器通常在事务 AOP 拦截器之前执行。

场景: 一个带有 @Transactional​ 和 @CachePut​ 的 updateUser​ 方法。

  1. ​@CachePut​ 执行,更新 Redis 缓存。
  2. ​@Transactional​ 开始事务。
  3. 方法体执行,更新数据库。
  4. 如果此时数据库更新失败,事务回滚。
  5. 结果: 数据库回滚了,但 Redis 缓存已经被更新为“新”数据,导致数据不一致(脏数据)。

最佳实践:分离关注点或延迟操作

  • 分离方法 (推荐): 将数据库操作放在一个纯粹的 @Transactional​ 方法中,然后在调用该方法的外部、非事务方法中处理缓存更新/清除逻辑。
   @Servicepublic class UserFacade { // 无事务@Autowiredprivate UserService userService; // 包含事务方法@CachePut(value = "user:info", key = "#user.id") // 缓存操作在事务外部public User updateUserAndCache(User user) {return userService.updateUserInTransaction(user); // 调用事务方法}@CacheEvict(value = "user:info", key = "#id")public void deleteUserAndEvictCache(Long id) {userService.deleteUserInTransaction(id);}}@Servicepublic class UserServiceImpl implements UserService { // 纯事务@Transactionalpublic User updateUserInTransaction(User user) {// ... 更新数据库 ...// if (someError) throw new RuntimeException("DB update failed");return user;}@Transactionalpublic void deleteUserInTransaction(Long id) {// ... 删除数据库 ...}}
  • 事务同步管理器 (较复杂): 使用 TransactionSynchronizationManager.registerSynchronization​ 注册一个回调,在事务成功提交后才执行缓存操作。这需要更复杂的编码。

关键: 尽量避免在同一个方法上混合 @Transactional​ 和写操作的缓存注解 (@CachePut​, @CacheEvict​)。优先选择分离方法。

5. AOP 的限制:内部调用失效之谜

问题: 在同一个 Service 类中,一个没有缓存注解的方法 A 调用了同一个类中带有 @Cacheable​ 的方法 B,你会发现方法 B 的缓存逻辑没有生效。

@Service
public class MyService {@Cacheable("myCache")public String cachedMethod(String key) {System.out.println("Executing cachedMethod for key: " + key);return "Data for " + key;}public String callingMethod(String key) {System.out.println("Calling cachedMethod internally...");// !!! 内部调用,cachedMethod 的缓存注解会失效 !!!return this.cachedMethod(key);}
}

原因: Spring AOP (包括缓存) 是通过代理实现的。外部调用 Service Bean 的方法时,访问的是代理对象,代理对象会执行缓存等切面逻辑。但是,当 Bean 的一个方法直接调用同一个 Bean 的另一个方法时 (this.methodB()​),它绕过了代理,直接调用了原始对象的方法,导致 AOP 切面(缓存注解)失效。

最佳实践:通过代理调用

  • 注入自身 (常用): 将 Service 自身注入到自己中,然后通过注入的实例来调用目标方法。
   @Servicepublic class MyService {@Autowiredprivate MyService self; // 注入自身代理@Cacheable("myCache")public String cachedMethod(String key) {System.out.println("Executing cachedMethod for key: " + key);return "Data for " + key;}public String callingMethod(String key) {System.out.println("Calling cachedMethod via self-proxy...");// 通过代理调用,缓存注解会生效return self.cachedMethod(key);}}

注意: 可能需要配置 Spring 允许循环依赖(虽然在新版本 Spring Boot 中,对于单例 Bean 的 Autowired​ 注入通常是允许的)。

  • 移到另一个 Bean (更清晰): 将需要被缓存的方法 (cachedMethod​) 移到另一个独立的 Bean 中,然后在 MyService​ 中注入并调用这个新的 Bean。这是更推荐的解耦方式。

关键: 理解 Spring AOP 代理机制是解决内部调用失效问题的关键。

总结

Spring Cache 与 Redis 的结合为 Java 应用带来了巨大的性能优势和开发便利。然而,魔鬼藏在细节中。关注 序列化选择、Key 的设计、TTL 的设置、事务交互 以及 AOP 代理限制 这些关键点,并遵循相应的最佳实践,将帮助你构建出更加健壮、高效、易于维护的缓存系统。希望这篇避坑指南能让你在未来的开发中更加得心应手!


相关文章:

精通 Spring Cache + Redis:避坑指南与最佳实践

Spring Cache 以其优雅的注解方式&#xff0c;极大地简化了 Java 应用中缓存逻辑的实现。结合高性能的内存数据库 Redis&#xff0c;我们可以轻松构建出响应迅速、扩展性强的应用程序。然而&#xff0c;在享受便捷的同时&#xff0c;一些常见的“坑”和被忽视的最佳实践可能会悄…...

DSP28335入门学习——第一节:工程项目创建

写这个文章是用来学习的,记录一下我的学习过程。希望我能一直坚持下去,我只是一个小白,只是想好好学习,我知道这会很难&#xff0c;但我还是想去做&#xff01; 本文写于&#xff1a;2025.04.20 DSP28335开发板学习——第一节&#xff1a;工程项目创建 前言开发板说明引用解答…...

Docker Registry(镜像仓库)

官方架构 Docker 使用客户端 - 服务器 (C/S) 架构模式&#xff0c;使用远程 API 来管理和创建 Docker 容器。Docker 容器通过 Docker 镜像来创建。 Docker 仓库(Registry)&#xff1a;Docker 仓库用来保存镜像&#xff0c;可以理解为代码控制中的代码仓库。Docker Hu…...

通过Dify快速搭建本地AI智能体开发平台

1. 安装Docker Desktop 访问 Docker官网 点击Download Docker Desktop&#xff0c;直接按照官方要求来就可以。 # 这串命令就像魔法咒语&#xff0c;在黑色窗口&#xff08;命令提示符&#xff09;里输入就能检查安装是否成功 docker --version2.安装dify 3.运行 Ollama 大…...

计算机视觉与深度学习 | Transformer原理,公式,代码,应用

Transformer 详解 Transformer 是 Google 在 2017 年提出的基于自注意力机制的深度学习模型,彻底改变了序列建模的范式,解决了 RNN 和 LSTM 在长距离依赖和并行计算上的局限性。以下是其原理、公式、代码和应用的详细解析。 一、原理 核心架构 Transformer 由 编码器(Encod…...

skywalking agent 关联docker镜像

Apache SkyWalking 提供了多种方式来部署和使用 SkyWalking Agent&#xff0c;包括在 Docker 容器中运行的应用。虽然 SkyWalking Agent 本身不是一个独立的 Docker 镜像&#xff0c;但你可以通过几种方式将 SkyWalking Agent 集成到你的 Docker 应用中。 方式一&#xff1a;手…...

【中间件】nginx将请求负载均衡转发给网关,网关再将请求转发给对应服务

一、场景 前端将请求发送给nginx&#xff0c;nginx将请求再转发给网关&#xff0c;网关再将请求转发至对应服务。由于网关会部署在多台服务器上&#xff0c;因此nginx需要负载均衡给网关发请求。nginx所有配置均参照官方文档nginx开发文档&#xff0c;可参考负载均衡板块内容 二…...

Milvus(1):什么是 Milvus

Milvus 由 Zilliz 开发&#xff0c;并很快捐赠给了 Linux 基金会下的 LF AI & Data 基金会&#xff0c;现已成为世界领先的开源向量数据库项目之一。它采用 Apache 2.0 许可发布&#xff0c;大多数贡献者都是高性能计算&#xff08;HPC&#xff09;领域的专家&#xff0c;擅…...

第十六节:高频开放题-React与Vue设计哲学差异

响应式原理&#xff08;Proxy vs 虚拟DOM&#xff09; 组合式API vs Hooks React 与 Vue 设计哲学差异深度解析 一、响应式原理的底层实现差异 1. Vue 的响应式模型&#xff08;Proxy/数据劫持&#xff09; Vue 的响应式系统通过 数据劫持 实现自动依赖追踪&#xff1a; • …...

【Hot100】 240. 搜索二维矩阵 II

目录 引言搜索二维矩阵 II我的解题贪心求解解题思路详解搜索策略&#xff08;以从右上角开始为例&#xff09;为什么这种方法有效&#xff1f; 完整代码实现复杂度分析示例演示 &#x1f64b;‍♂️ 作者&#xff1a;海码007&#x1f4dc; 专栏&#xff1a;算法专栏&#x1f4a…...

每日面试实录·携程·社招·JAVA

&#x1f4cd;面试公司&#xff1a;携程 &#x1f45c;面试岗位&#xff1a;后端开发工程师&#xff08;社招&#xff09; &#x1f550;面试时长&#xff1a;约 50 分钟 &#x1f504;面试轮次&#xff1a;第 1 轮技术面 ✨面试整体节奏&#xff1a; 这场携程的社招 Java 一面…...

Oracle--用户管理

前言&#xff1a;本博客仅作记录学习使用&#xff0c;部分图片出自网络&#xff0c;如有侵犯您的权益&#xff0c;请联系删除 用户管理在 Oracle 数据库中至关重要。一个服务器通常只运行一个 Oracle 实例&#xff0c;而一个 Oracle 用户代表一个用户群&#xff0c;他们通过该用…...

20.3 使用技巧5

版权声明&#xff1a;本文为博主原创文章&#xff0c;转载请在显著位置标明本文出处以及作者网名&#xff0c;未经作者允许不得用于商业目的 20.3.8 CellContentClick事件 当增加新按钮列或者超链接列后&#xff0c;按钮或者超链接&#xff0c;会发现&#xff0c;按钮或者超链…...

Kubernetes相关的名词解释Metrics Server组件(7)

什么是Metrics Server&#xff1f; Metrics Server 是 Kubernetes 集群中的一个关键组件&#xff0c;主要用于资源监控和自动扩缩容。 kubernetes 从1.8版本开始不再集成cadvisor&#xff0c;也废弃了heapster&#xff0c;使用metrics server来提供metrics。那么...... 什么…...

17.【.NET 8 实战--孢子记账--从单体到微服务--转向微服务】--单体转微服务--SonarQube部署与配置

在将孢子记账系统从单体架构转向微服务架构的过程中&#xff0c;代码质量的管理变得尤为重要。随着项目规模的扩大和团队协作的深入&#xff0c;我们需要一个强大的工具来帮助我们持续监控和改进代码质量。我们首选SonarQube&#xff0c;它能够帮助我们识别代码中的潜在问题、技…...

计算机是如何看待数据的?

一、计算机如何“看待”数据&#xff1f; 物理层本质&#xff1a; 计算机的所有数据最终以二进制&#xff08;0和1&#xff09;在电路中表示&#xff08;高电平1&#xff0c;低电平0&#xff09;。 无论你用何种进制描述数据&#xff08;如十六进制 0xA1 或十进制 161&#xf…...

25.4.20学习总结

如何使用listView组件来做聊天界面 1. 什么是CellFactory&#xff1f; 在JavaFX中&#xff0c;控件&#xff08;比如ListView、TableView等&#xff09;用Cell来显示每一条数据。 Cell&#xff1a;代表这个单元格&#xff08;即每个列表项&#xff09;中显示的内容和样式。 …...

SpringBoot3集成ES8.15实现余额监控

1. gradle依赖新增 implementation org.springframework.boot:spring-boot-starter-data-elasticsearch implementation co.elastic.clients:elasticsearch-java:8.15.02. application.yml配置 spring:elasticsearch:uris: http://localhost:9200username: elasticpassword: …...

STM32基础教程——串口收发

目录 前言 字长设置 ​编辑 停止位 起始位侦测 波特率 1. UART波特率的基本原理 2. 为什么需要先除以分频因子&#xff08;USARTDIV&#xff09;&#xff1f; &#xff08;1&#xff09;PCLK频率太高 &#xff08;2&#xff09;分频因子的作用 3. 为什么还需要再除以…...

Matlab 步进电机传递函数模糊pid

1、内容简介 Matlab 210-步进电机传递函数模糊pid 可以交流、咨询、答疑 2、内容说明 略 3、仿真分析 略 4、参考论文 略...

unordered_map、unordered_set详解

深入理解C中的 unordered_map 和 unordered_set 在C标准库中&#xff0c;unordered_map 和 unordered_set 是两个基于‌哈希表&#xff08;Hash Table&#xff09;‌实现的高效容器。它们以‌O(1)‌的平均时间复杂度实现快速查找、插入和删除操作&#xff0c;特别适合需要高频…...

详解trl中的GRPOTrainer和GRPOConfig

引言 在大型语言模型(LLM)的强化学习微调领域, Group Relative Policy Optimization (GRPO) 算法因其高效性和资源友好性受到广泛关注。Hugging Face的 TRL (Transformer Reinforcement Learning) 库通过GRPOTrainer和GRPOConfig提供了该算法的开箱即用实现。本文将深入解析…...

【C++】多态 - 从虚函数到动态绑定的核心原理

&#x1f4cc; 个人主页&#xff1a; 孙同学_ &#x1f527; 文章专栏&#xff1a;C &#x1f4a1; 关注我&#xff0c;分享经验&#xff0c;助你少走弯路 文章目录 1. 多态的概念2. 多态的定义及实现2.1 多态的构成条件2.1.1实现多态还有两个必须重要条件&#xff1a;2.1.2 虚…...

项目预期管理:超越甘特图,实现客户价值交付

引言 在项目管理实践中&#xff0c;许多项目经理习惯于将注意力集中在甘特图的进度条上&#xff0c;关注任务是否按时完成、里程碑是否达成。然而&#xff0c;这种以计划管理为中心的方法往往忽略了项目管理的核心目标&#xff1a;满足客户预期&#xff0c;交付真正的价值。项…...

FISCO 2.0 安装部署WeBASE与区块链浏览器(环境搭建)

FISCO BCOS 2.0 安装部署WeBASE与区块链浏览器-对应的官网地址&#xff1a; WeBASE平台&#xff1a;https://webasedoc.readthedocs.io/zh-cn/latest/docs/WeBASE/install.html 区块链浏览器&#xff1a;https://fisco-bcos-documentation.readthedocs.io/zh-cn/latest/docs/br…...

xss学习3之服务端session

一、服务端的Session 1. cookie和session 1&#xff09;cookie和session对比 cookie: 保存在客户端&#xff0c;包含所有key-value信息&#xff0c;浏览器访问多个网站时会积累大量cookie&#xff0c;占用存储空间&#xff0c;并在每次请求时携带所有cookie&#xff0c;增加…...

23种设计模式-结构型模式之适配器模式(Java版本)

Java 适配器模式&#xff08;Adapter Pattern&#xff09;详解 &#x1f50c; 什么是适配器模式&#xff1f; 适配器模式用于将一个类的接口转换成客户端所期望的另一种接口&#xff0c;让原本接口不兼容的类可以协同工作。 &#x1f4e6; 就像插头转换器&#xff0c;让不同…...

【2025计算机网络-面试常问】http和https区别是什么,http的内容有哪些,https用的是对称加密还是非对称加密,流程是怎么样的

HTTP与HTTPS全面对比及HTTPS加密流程详解 一、HTTP与HTTPS核心区别 特性HTTPHTTPS协议基础明文传输HTTP SSL/TLS加密层默认端口80443加密方式无加密混合加密&#xff08;非对称对称&#xff09;证书要求不需要需要CA颁发的数字证书安全性易被窃听、篡改、冒充防窃听、防篡改…...

使用安全继电器的急停电路设计

使用安全继电器的急停电路设计 一&#xff0c;急停回路的设计1&#xff0c;如何将急停接到线路当中&#xff1f;2&#xff0c;急停开关 如何接到安全继电器中 一&#xff0c;急停回路的设计 急停是每一个设备必不可少的部分&#xff0c;因为关乎安全&#xff0c;所以说所以说他…...

SpringCloud概述和环境搭建

SpringCloud概述和环境搭建 一.微服务的引入1.单体架构2.集群和分布式架构3.集群和分布式4.微服务架构4.微服务的优缺点 二.微服务解决方案-SpringCloud1.Spring Cloud简介2.Spring Cloud版本3.Spring Cloud实现方案4.Spring Cloud Alibaba 三.环境搭建1.安装JDK172.Ubantu上下…...

System.out 详解

System.out 详解 System.out 是 Java 提供的标准输出流(PrintStream 类型),默认关联控制台(Console),用于向终端打印文本信息。它是 Java 中最常用的输出方式之一,尤其在调试和命令行程序开发中。 1. 核心知识点 (1)System.out 的本质 类型:PrintStream(字节流,但…...

每天学一个 Linux 命令(28):ln

​​可访问网站查看,视觉品味拉满: http://www.616vip.cn/28/index.html ln 是 Linux 中用于创建文件或目录链接的命令,主要生成硬链接(Hard Link)和符号链接(Symbolic Link,软链接)。链接常用于文件共享、快捷访问或版本管理。 命令格式 ln [选项] 源文件 目标链接链…...

【微知】服务器如何获取服务器的SN序列号信息?(dmidecode -t 1)

文章目录 背景命令dmidecode -t的数字代表的字段 背景 各种场景都需要获取服务器的SN&#xff08;Serial Number&#xff09;&#xff0c;比如问题定位&#xff0c;文件命名&#xff0c;该部分信息在dmi中是标准信息&#xff0c;不同服务器&#xff0c;不同os都能用相同方式获…...

4.20刷题记录(单调栈)

第一部分&#xff1a;简单介绍 单调栈我的理解是在栈中存储数字出现的位置&#xff0c;然后通过遍历比较当前栈顶元素与当前元素的大小关系&#xff0c;从而确定逻辑相关顺序。 第二部分&#xff1a;真题讲解 &#xff08;1&#xff09;739. 每日温度 - 力扣&#xff08;Lee…...

Opencv图像处理:模板匹配对象

文章目录 一、模板匹配1、什么是模板匹配&#xff1f;2、原理 二、单模板匹配&#xff08;代码实现&#xff09;1、预处理2、 开始模板匹配并绘制匹配位置的外接矩形 三、多模板匹配&#xff08;代码实现&#xff09;1、读取图片和模板2、模板匹配3、设置阈值1&#xff09;阈值…...

Web3.0热门领域NFT项目实战课程

课程大小&#xff1a;3.8G 课程下载&#xff1a;https://download.csdn.net/download/m0_66047725/90616383 更多资源下载&#xff1a;关注我 深度掌握Solidity合约开发&#xff0c;助力成为抢手的Web3.0开发工程师 深入Web3.0技术的人才&#xff0c;一将难求。本课程由We…...

DAY 50 leetcode 1047--栈和队列.删除字符串中的所有相邻重复项

题号1047 给出由小写字母组成的字符串 s&#xff0c;重复项删除操作会选择两个相邻且相同的字母&#xff0c;并删除它们。 在 s 上反复执行重复项删除操作&#xff0c;直到无法继续删除。 在完成所有重复项删除操作后返回最终的字符串。答案保证唯一。 import java.util.Ar…...

单例模式与消费者生产者模型,以及线程池的基本认识与模拟实现

前言 今天我们就来讲讲什么是单例模式与线程池的相关知识&#xff0c;这两个内容也是我们多线程中比较重要的内容。其次单例模式也是我们常见设计模式。 单例模式 那么什么是单例模式呢&#xff1f;上面说到的设计模式又是什么&#xff1f; 其实单例模式就是设计模式的一种。…...

微信小程序通过mqtt控制esp32

目录 1.注册巴法云 2.设备连接mqtt 3.微信小程序 备注 本文esp32用的是MicroPython固件&#xff0c;MQTT服务用的是巴法云。 本文参考巴法云官方教程&#xff1a;https://bemfa.blog.csdn.net/article/details/115282152 1.注册巴法云 注册登陆并新建一个topic&#xff…...

QML、Qt Quick 、Qt Quick Controls 2

一、概念 基本关系 QML 是声明式语言,用于描述用户界面。声明式语法(类似JSON+JavaScript),定义UI结构和行为。 Qt Quick 是 QML 的标准库,提供基本类型和功能。提供QML语言运行时的基础能力,相当于QML的"标准模板库(STL)"。 Quick Controls 2 是基于 Qt Quic…...

基于maven-jar-plugin打造一款自动识别主类的maven打包插件

&#x1f9d1; 博主简介&#xff1a;CSDN博客专家&#xff0c;历代文学网&#xff08;PC端可以访问&#xff1a;https://literature.sinhy.com/#/?__c1000&#xff0c;移动端可微信小程序搜索“历代文学”&#xff09;总架构师&#xff0c;15年工作经验&#xff0c;精通Java编…...

利用 HEMT 和 PHEMT 改善无线通信电路中的增益、速度和噪声

本文要点 高电子迁移率晶体管 &#xff08;High electron mobility transistors &#xff0c;HEMTs&#xff09; 和应变式异质接面高迁移率晶体管&#xff08;pseudomorphic high electron mobility transistors &#xff0c;PHEMTs&#xff09; 因其独特的、可提高性能的特点而…...

探秘C#用户定义类型:突破预定义的边界

在C#的编程世界里&#xff0c;除了系统提供的16种预定义类型&#xff0c;开发者还拥有强大的自主能力——创建自己的用户定义类型。这大大拓展了编程的灵活性和可扩展性&#xff0c;让开发者能根据具体需求定制数据结构和功能。 六种用户定义类型 类类型&#xff08;class&am…...

idea中导入从GitHub上克隆下来的springboot项目解决找不到主类的问题

第一步&#xff1a;删除目录下的.idea和target&#xff0c;然后用idea打开 第二步&#xff1a;如果有需要&#xff0c;idea更换jdk版本 原文链接&#xff1a;https://blog.csdn.net/m0_74036731/article/details/146779040 解决方法&#xff08;idea中解决&#xff09;&#…...

北理工宫某的瓜ppt下载地址

关于“北理工宫某瓜”PPT下载地址相关技术探讨 摘要&#xff1a;本文围绕“北理工宫某瓜”事件中PPT下载地址相关情况展开分析&#xff0c;探讨了网络资源传播的技术机制、涉及的网络安全问题以及围绕此类资源分享应遵循的规范和注意事项&#xff0c;旨在从技术角度对这类网络…...

[论文阅读]Making Retrieval-Augmented Language Models Robust to Irrelevant Context

Making Retrieval-Augmented Language Models Robust to Irrelevant Context [2310.01558v2] Making Retrieval-Augmented Language Models Robust to Irrelevant Context 检索增强语言模型&#xff08;RALMs&#xff09;&#xff0c;它包含一个检索机制&#xff0c;以减少将…...

论文阅读:2023 arxiv A Survey of Reinforcement Learning from Human Feedback

A Survey of Reinforcement Learning from Human Feedback https://arxiv.org/pdf/2312.14925 https://www.doubao.com/chat/3506943124865538 速览 这篇论文是关于“从人类反馈中进行强化学习&#xff08;RLHF&#xff09;”的综述&#xff0c;核心是讲如何让AI通过人类反…...

【图像处理基石】什么是去马赛克算法?

RAW数据的Demosaic算法&#xff08;去马赛克算法&#xff09;是图像处理中的关键技术&#xff0c;主要用于将图像传感器&#xff08;如数码相机、手机摄像头&#xff09;采集的原始马赛克数据恢复为完整的RGB三通道图像。 1. RAW数据的特性 马赛克结构&#xff1a;图像传感器…...

transformer注意力机制

单头注意力机制 import torch import torch.nn.functional as Fdef scaled_dot_product_attention(Q, K, V):# Q: (batch_size, seq_len, d_k)# K: (batch_size, seq_len, d_k)# V: (batch_size, seq_len, d_v)batch_size: 一次输入的句子数。 seq_len: 每个句子的词数。 d_mo…...

Ubuntu 22.04 更换 Nvidia 显卡后启动无法进入桌面问题的解决

原显卡为 R7 240, 更换为 3060Ti 后, 开机进桌面时卡在了黑屏界面, 键盘有反应, 但是无法进入 shell. 解决方案为 https://askubuntu.com/questions/1538108/cant-install-rtx-4060-ti-on-ubuntu-22-04-lts 启动后在开机菜单中(如果没有开机菜单, 需要按shift键), 进入recove…...