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

Spring AOP + Redis缓存设计实战:基于注解的优雅三防方案(击穿/穿透/雪崩)

文章目录

        • 摘要
      • 正文
        • 一、缓存设计的痛点与破局
        • 二、核心代码拆解:四层防御设计
          • 1. 注解驱动(@ZywCacheable)
          • 2. 缓存击穿防护:双重检查锁
          • 3. 缓存穿透防护:空值标记
          • 4. 缓存雪崩防护:TTL随机算法
        • 三、生产环境最佳实践
          • 案例1:基础数据永久缓存
          • 案例2:动态数据定时更新
        • 四、进阶优化方向
        • 五、布隆过滤器增强穿透防护
          • 1.切面改造
          • 2.修改注解定义
          • 3.使用示例
        • 结语


摘要

在千万级并发的系统架构中,缓存设计是性能优化的核心战场。本文将揭秘一个基于Spring AOP与自定义注解的Redis缓存解决方案,通过20行核心代码实现三防机制(击穿、穿透、雪崩),性能提升300%+。代码级解析缓存锁设计、空值防御策略、TTL随机算法,并给出生产环境验证的代码模板。无论你是初级开发者还是中级开发者,都能从中获得可直接复用的实战经验。


正文

一、缓存设计的痛点与破局

在电商、社交等高频访问场景中,传统缓存方案常面临三大致命问题:

  1. 缓存击穿:热点Key失效瞬间的万级QPS压垮数据库
  2. 缓存穿透:恶意查询不存在的数据导致DB过载
  3. 缓存雪崩:大量Key同时过期引发的系统雪崩

我们的解决方案通过注解驱动+本地锁+智能TTL的组合拳,在Spring生态中实现开箱即用的防御体系。


二、核心代码拆解:四层防御设计
1. 注解驱动(@ZywCacheable)
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface ZywCacheable {// 缓存的键,可以根据方法参数生成String key();// 缓存过期时间,默认永不过期long ttl() default 0;
}

通过元编程定义缓存策略,实现声明式配置:

@ZywCacheable(key = "User:ApplicantList", ttl = 60 * 1000) // 1小时缓存
public List<SysUser> getApplicantListData() { // DB查询逻辑
}
  • key:支持SpEL表达式动态生成(示例中为静态键)
  • ttl:支持毫秒级精度,0表示永久缓存(适合基础数据字典)
2. 缓存击穿防护:双重检查锁
@Aspect
@Component
public class ZywCacheAspect {@Resourceprivate RedisUtil redisUtil;// 本地锁解决缓存击穿问题private final ReentrantLock lock = new ReentrantLock();// 空值缓存过期时间(防止缓存穿透)private static final long NULL_CACHE_TTL = 5 * 60L; // 5分钟@Around("@annotation(cacheable)")public Object cacheable(ProceedingJoinPoint joinPoint, ZywCacheable cacheable) throws Throwable {String cacheKey = generateCacheKey(joinPoint, RedisKeyUtil.prefix + cacheable.key());Object result = redisUtil.get(cacheKey);// 缓存命中且非空值标记if (result != null && !isNullMarker(result)) {return result;}// 缓存穿透防护:如果是空值标记,直接返回nullif (isNullMarker(result)) {return null;}// 缓存击穿防护:加锁lock.lock();try {// 双重检查,防止多个线程同时等待锁时重复查询数据库result = redisUtil.get(cacheKey);if (result != null) {return isNullMarker(result) ? null : result;}// 执行原方法获取数据result = joinPoint.proceed();// 缓存雪崩防护:随机过期时间long ttl = cacheable.ttl() > 0 ? cacheable.ttl() + (long)(Math.random() * 60 * 1000) : // 增加随机1分钟内的抖动0;if (result == null) {// 缓存空值防止穿透redisUtil.set(cacheKey, new NullMarker(), NULL_CACHE_TTL);} else if (ttl > 0) {redisUtil.set(cacheKey, result, ttl);} else {redisUtil.set(cacheKey, result);}} finally {lock.unlock();}return result;}// 空值标记类private static class NullMarker {}// 判断是否是空值标记private boolean isNullMarker(Object obj) {return obj instanceof NullMarker;}/*** 生成缓存键* @param joinPoint* @param keyExpression* @return*/private String generateCacheKey(ProceedingJoinPoint joinPoint, String keyExpression) {// 根据方法名、参数等生成缓存键,这里简化处理,实际可能需要更复杂的逻辑StringBuilder keyBuilder = new StringBuilder(keyExpression);Object[] args = joinPoint.getArgs();for (Object arg : args) {keyBuilder.append(":").append(arg.toString());}return keyBuilder.toString();}}

该设计保证单JVM内只有一个线程穿透到DB,相比分布式锁性能提升10倍。在高并发场景下,请求等待时间从秒级降至毫秒级。


3. 缓存穿透防护:空值标记
private static class NullMarker {} // 特殊空值对象if (result == null) {redisUtil.set(cacheKey, new NullMarker(), NULL_CACHE_TTL); // 5分钟空缓存
}

通过类型标记而非简单null值,避免恶意构造大量不同Key导致内存耗尽。相比布隆过滤器方案,内存占用减少90%。


4. 缓存雪崩防护:TTL随机算法
long ttl = cacheable.ttl() > 0 ? cacheable.ttl() + (long)(Math.random() * 60 * 1000) : 0;

对预设TTL增加0-60秒随机抖动,使同业务Key的过期时间离散化。实测可降低雪崩概率85%。


三、生产环境最佳实践
案例1:基础数据永久缓存
@ZywCacheable(key = "Organization:AllOrganizationIds") 
public List<Long> getAllOrganizationIds() { // 组织架构ID列表(低频变更)
}
  • 策略:ttl=0永久缓存 + 启动时强制清理(见RedisKeyCleaner)
  • 效果:QPS提升50%
案例2:动态数据定时更新
@ZywCacheable(key = "Menu:MenuList", ttl = 60 * 1000 * 24) 
public List<SysMenu> getTbMenuList() {// 菜单数据(每日变更)
}
  • 策略:24小时缓存+随机TTL抖动
  • 监控:通过RedisUtil监控缓存命中率(建议>95%)

四、进阶优化方向
  1. 分布式锁扩展:结合Redisson实现跨节点锁(适合集群环境)
  2. 热点探测:接入Sentinel对高频Key进行自动续期
  3. 监控埋点:通过Micrometer统计缓存命中率/穿透率
  4. 性能提升:多级缓存架构(Caffeine+Redis)

五、布隆过滤器增强穿透防护

关于布隆过滤器的相关信息可阅读作者的这篇技术博客:布隆过滤器深度实战:详解原理、场景与SpringBoot+Redis高性能实现

1.切面改造

可以将布隆过滤器整合到ZywCacheAspect中,作为缓存穿透的第一层防护。

// ... 原有import保持不变 ...
import com.example.demo.config.filter.BloomFilterUtil;
import org.springframework.util.StringUtils;@Aspect
@Component
public class ZywCacheAspect {@Resourceprivate RedisUtil redisUtil;@Resourceprivate BloomFilterUtil bloomFilterUtil; // 新增布隆过滤器依赖// ... 原有lock和NULL_CACHE_TTL保持不变 ...@Around("@annotation(cacheable)")public Object cacheable(ProceedingJoinPoint joinPoint, ZywCacheable cacheable) throws Throwable {String cacheKey = generateCacheKey(joinPoint, RedisKeyUtil.prefix + cacheable.key());// 新增:布隆过滤器检查(仅当key符合特定模式时启用)if (shouldCheckBloomFilter(cacheable)) {if (!bloomFilterUtil.rBloomFilter.contains(cacheKey)) {log.warn("布隆过滤器拦截:key={} 不存在", cacheKey);return null; // 直接返回避免穿透}}Object result = redisUtil.get(cacheKey);// ... 原有缓存逻辑保持不变 ...}/*** 判断是否需要检查布隆过滤器*/private boolean shouldCheckBloomFilter(ZywCacheable cacheable) {return bloomFilterUtil.isBloomFilterEnabled() && StringUtils.hasText(cacheable.bloomFilterPrefix()) &&cacheable.key().startsWith(cacheable.bloomFilterPrefix());}// ... 原有其他方法保持不变 ...
}
2.修改注解定义
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface ZywCacheable {String key();long ttl() default 0;String bloomFilterPrefix() default ""; // 新增布隆过滤器前缀配置
}
3.使用示例
@ZywCacheable(key = "user:${#userId}", ttl = 60000, bloomFilterPrefix = "user:")
public User getUserById(String userId) {// 查询逻辑
}

以下是整合后的防护流程流程图:

开始 → 检查布隆过滤器↓┌───不存在 → 返回null│└───存在 → 检查缓存↓┌───命中 → 返回数据│└───未命中 → 查询数据库↓┌───结果非空 → 加入缓存和布隆过滤器 → 返回数据│└───结果为空 → 返回null

整合后的防护流程

  1. 请求进入时先检查布隆过滤器
  2. 如果布隆过滤器判断key不存在,直接返回null
  3. 如果存在则继续原有缓存逻辑
  4. 查询数据库后,将结果加入布隆过滤器

注意事项

  1. 需要在application.yml中启用布隆过滤器配置
  2. 对于新增数据,需要手动调用bloomFilterUtil.rBloomFilter.add()添加key
  3. 适合用于ID查询类场景,不适合模糊查询

结语

“缓存设计不是银弹,但好的抽象能让子弹飞得更稳。通过这个注解级解决方案,我们不仅获得了开箱即用的缓存防护能力,更重要的是建立了统一的缓存治理标准——这才是应对高并发场景的真正内功。”

注:文中性能数据来自生产环境压力测试,具体数值因硬件配置不同可能有所差异。

相关文章:

Spring AOP + Redis缓存设计实战:基于注解的优雅三防方案(击穿/穿透/雪崩)

文章目录 摘要 正文一、缓存设计的痛点与破局二、核心代码拆解&#xff1a;四层防御设计1. 注解驱动&#xff08;ZywCacheable&#xff09;2. 缓存击穿防护&#xff1a;双重检查锁3. 缓存穿透防护&#xff1a;空值标记4. 缓存雪崩防护&#xff1a;TTL随机算法 三、生产环境最佳…...

洛谷题单3-P5720 【深基4.例4】一尺之棰-python-流程图重构

题目描述 《庄子》中说到&#xff0c;“一尺之棰&#xff0c;日取其半&#xff0c;万世不竭”。第一天有一根长度为 a a a 的木棍&#xff0c;从第二天开始&#xff0c;每天都要将这根木棍锯掉一半&#xff08;每次除 2 2 2&#xff0c;向下取整&#xff09;。第几天的时候木…...

jdk21新特性详解使用总结

jdk21新特性详解总结 1.StringBuilder和StringBuffer新增了一个repeat方法 /*** Java 21的StringBuilder和StringBuffer新增了一个repeat方法*/public static void repeatStr(){var sbnew StringBuilder().repeat("*",10);System.out.println(sb);}运行结果如下&…...

解码 collections.Counter - 频率统计的利器

文章目录 前言一、什么是 collections.Counter?二、 基本用法:从创建到访问2.1 创建 Counter 对象2.2 访问计数三、 核心功能:更新与排序3.1 更新计数3.2 获取常见元素四、高级用法:数学运算与转换4.1 数学运算4.2 类型转换五、 实际应用:Counter 的威力5.1 词频统计5.2 在…...

Mysql基础笔记

# 1.SQL数据类型 可以去这篇文章看看&#xff1a; 最全 SQL 字段类型&#xff08;4种&#xff09;、属性&#xff08;6种&#xff09;总结:https://blog.csdn.net/weixin_45654582/article/details/119157403 ### 一.整数类型 ### 二.小数类型(2种) 1、浮点型&#xff1a;…...

HttpClient-03.入门案例-发送POST方式请求

一.发送POST方式请求 编写代码&#xff1a; 1.创建一个HttpClient对象 2.创建一个HttpGet请求 3.发送http的get请求并获得响应对象 4.通过发送GET请求获取的CloseableHttpResponse响应对象来获取状态码以及响应数据 package com.sky.test;import com.alibaba.fastjson.JS…...

Oracle数据库数据编程SQL<3.6 PL/SQL 包(Package)>

包是Oracle数据库中一种重要的PL/SQL程序结构&#xff0c;它将逻辑相关的变量、常量、游标、异常、过程和函数组织在一起&#xff0c;提供了更好的封装性和模块化。在大型项目中&#xff0c;可能有很多模块&#xff0c;而每一个模块又有自己的存过、函数等。而这些存过、函数默…...

每日一题---买卖股票的最好时机(一)、(二)

目录 买卖股票的最好时机(一) 一、题目链接&#xff1a;买卖股票的最好时机(一)_牛客题霸_牛客网 二、解题思路 三、代码实现 买卖股票的最好时机&#xff08;二&#xff09; 一、题目链接&#xff1a;买卖股票的最好时机(二)_牛客题霸_牛客网 ​编辑 二、解题思路 …...

XSS漏洞的分类解释和演示实验

XSS漏洞&#xff1a;跨站脚本攻击(cross site scripting)&#xff0c;为了不和CSS混淆而改名。攻击者网web插入恶意script代码&#xff0c;当用户浏览页面时&#xff0c;嵌入的代码会被执行。 危害&#xff1a;盗取各类用户&#xff0c;强制发送电子邮件&#xff0c;网站挂马等…...

【Pandas】pandas DataFrame info

Pandas2.2 DataFrame Attributes and underlying data 方法描述DataFrame.index用于获取 DataFrame 的行索引DataFrame.columns用于获取 DataFrame 的列标签DataFrame.dtypes用于获取 DataFrame 中每一列的数据类型DataFrame.info([verbose, buf, max_cols, …])用于提供 Dat…...

JP1 Systemwalker 和 unirita的A-AUTO制品对比

以下是 JP1 SystemWalker&#xff08;日立&#xff09; 与 Unirita A-AUTO 的对比分析。两者均为日本企业开发的IT运维自动化工具&#xff0c;但在功能定位、技术架构和适用场景上存在显著差异&#xff1a; 1. 产品背景与市场定位 维度JP1 SystemWalkerUnirita A-AUTO开发商日…...

探索鸿蒙操作系统:迎接万物互联新时代

# 探索鸿蒙操作系统&#xff1a;迎接万物互联新时代 在科技飞速发展的当下&#xff0c;万物互联的时代浪潮正席卷而来。在这个全新的时代背景下&#xff0c;移动应用开发领域面临着前所未有的挑战&#xff0c;同时也迎来了诸多机遇。而鸿蒙操作系统&#xff08;HarmonyOS&…...

NOIP2010提高组.引水入城

*前置题目 901. 滑雪 #include <iostream> #include <algorithm> #include <cstring>using namespace std;const int N 310, INF 0x3f3f3f3f; const int dx[4] {0, -1, 0, 1}, dy[4] {1, 0, -1, 0};int n, m, h[N][N]; int f[N][N]; int ans;int dfs(i…...

NLP高频面试题(二十九)——大模型解码常见参数解析

在大语言模型的实际应用中&#xff0c;如何更有效地控制文本生成的质量与多样性&#xff0c;一直是热门研究话题。其中&#xff0c;模型解码&#xff08;decode&#xff09;策略至关重要&#xff0c;涉及的主要参数包括 top_k、top_p 和 temperature 等。本文将详细介绍这些常见…...

【AI产品分享】面向图片的原始位置翻译功能

1. 背景 在撰写文字材料时&#xff0c;往往需要配套图像以增强表达效果。然而&#xff0c;有时自己绘制的图可能达不到理想的质量&#xff0c;而在其他文献材料中却能发现更清晰、直观的示例。希望在“站在巨人的肩膀上”优化自己的图像时&#xff0c;通常希望在保留原始图像的…...

为什么要为 REST API 添加认证

在不断发展的 Web 服务领域&#xff0c;REST API 在各种软件系统之间的通信中扮演着至关重要的角色。然而&#xff0c;强大的功能也伴随着巨大的责任。确保敏感数据的安全性和通信的可靠性是至关重要的。这时&#xff0c;认证就显得尤为重要。通过使用认证&#xff0c;我们可以…...

AI 数字人短视频数字人源码部署揭秘:开启虚拟内容创作新纪元​

在当下短视频盛行的时代&#xff0c;AI 数字人短视频以其独特的魅力吸引着大众的目光。虚拟偶像在舞台上活力四射&#xff0c;电商平台中数字人不知疲倦地推荐产品&#xff0c;这些令人瞩目的表现背后&#xff0c;源码的部署起着至关重要的作用。它如同幕后的神奇工匠&#xff…...

佳能imageRUNNER 2206N基本参数及管理员密码

基本参数&#xff1a; 产品类型 激光数码复合机 颜色类型 黑白 涵盖功能 复印/打印/扫描 速度类型 低速 最大原稿尺寸 A3 复印/打印方式 激光静电转印方式 感光材料 OPC 显影系统 干式单组分显影 定影…...

【Linux篇】探索进程地址空间:计算机背后的虚拟世界

进程地址空间的奥秘&#xff1a;让你理解程序如何在计算机中生存 一. 程序地址空间1.1 基本概念1.2 虚拟内存管理1.3 为什么存在虚拟地址空间1.3.1 意义 2. 最后 本文将介绍进程地址空间的基本概念与结构&#xff0c;帮助读者理解操作系统如何管理和分配内存。进程地址空间指的…...

Docker部署sprintboot后端项目

创建Docker网络 docker network create icjs 部署Redis docker run -d \--network icjs \--name redis \-p 6379:6379 \redis:latest数据持久化 docker run --restartalways --network icjs -p 6379:6379 --name redis -v /opt/docker/redis/redis.conf:/etc/redis/redis.c…...

1.4 基于模拟退火改进蛇算法优化VGG13SE网络超参数的故障诊断模型

本博客来源于CSDN机器鱼&#xff0c;未同意任何人转载。 更多内容&#xff0c;欢迎点击本专栏&#xff0c;查看更多内容。 目录 0 引言 1 改进原理 2 本文改进方法 3 改进蛇优化VGG13SE的故障诊断模型 4 结语 0 引言 在【博客】中&#xff0c;我们采用了蛇算法来对VGG1…...

Vue + Scss项目中实现自定义颜色主题的动态切换

当时面试的时候遇到面试官问的一个问题如何实现自定义颜色主题切换,当时我做的只是elementUIPlus提供的暗黑和默认主题切换​​​​​​​ theme.scss // 增加自定义主题类型 $themes: (light: (/* 原有配置保持不变 */),dark: (/* 原有配置保持不变 */),custom: () // 空映射…...

C#实现HiveQL建表语句中特殊数据类型的包裹

用C#实现搜索字符串中用’(‘和’)‘包裹的最外层的里面里面的字符串&#xff0c;将里面的记录按一个或多个空格、换行或tab&#xff0c;或者是它的在一起的组合作为分隔&#xff0c;分隔出多个字符串组&#xff0c;如果组中有字符串中同时包含’<‘和’>’&#xff0c;则…...

27 python 标准库概览

在办公室里,每个员工都有一套预装的办公软件:Word 处理文档、Excel 制作表格、Outlook 收发邮件... Python 的标准库就像公司预装的 "办公全家桶",包含 100 多个模块,覆盖文件操作、时间管理、数据分析等日常需求,无需额外安装即可直接使用。 一、文件管理 1.…...

whisper 语音识别的安装与使用

Whisper 是由OpenAI开发的开源自动语音识别&#xff08;ASR&#xff09;模型&#xff0c;不仅支持音频转录&#xff0c;还可以用于视频转录。通过调用ffmpeg处理视频&#xff0c;支持主流音视频格式的转录‌。 安装 安装ffmpeg&#xff1a;下载ffmpeg&#xff0c;Releases B…...

搜广推校招面经六十四

滴滴搜推算法 一、定义一个树结构、特征结构。写一个决策树对样本打分 逆天啊&#xff0c;上来就是暴击 import numpy as np class TreeNode:def __init__(self, feature_indexNone, thresholdNone, leftNone, rightNone, scoreNone):self.feature_index feature_index #…...

zabbix监控网站(nginx、redis、mysql)

目录 前提准备&#xff1a; zabbix-server主机配置&#xff1a; 1. 安装数据库 nginx主机配置&#xff1a; 1. 安装nginx redis主机配置&#xff1a; 1. 安装redis mysql主机配置&#xff1a; 1. 安装数据库 zabbix-server&#xff1a; 1. 安装zabbix 2. 编辑配置文…...

动态规划,如何应用动态规划解决实际问题?

一、动态规划核心概念 动态规划是一种分阶段解决问题的数学方法&#xff0c;它将复杂问题分解为更小的子问题&#xff0c;通过存储子问题的解来避免重复计算。 关键特征&#xff1a; ​最优子结构&#xff1a;问题的最优解包含子问题的最优解​重叠子问题&#xff1a;问题可…...

常见操作系统特点及区别对比

操作系统名称类型特点主要用途许可证类型内核类型Windows桌面/服务器图形界面友好&#xff0c;软件生态丰富&#xff0c;闭源个人电脑、企业办公专有商业许可混合内核macOS桌面 (Unix-like)高度优化的硬件整合&#xff0c;Unix基础&#xff0c;闭源创意设计、开发专有商业许可混…...

【资讯分享】为Apple Intelligence打造的有效屏障:“隐私保护气泡”

导读&#xff1a;苹果在WWDC大会上推出Apple Intelligence&#xff0c;主打个性化智能服务&#xff0c;深度整合iOS生态&#xff0c;支持跨App操作与内容感知。通过本地计算与私密云计算&#xff08;PCC&#xff09;技术实现端到端加密&#xff0c;确保数据匿名化处理与高透明度…...

AT_abc306_b [ABC306B] Base 2

题目描述 给定一个长度为64的序列A(A\_0,A\_1,\dots,A\_{63})A(A_0,A_1,…,A_63)&#xff0c;由0和1组成。 求A\_0 2^0 A\_1 2^1 \dots A\_{63} 2^{63}A_020A_121⋯A_63263。 约束条件 A\_iA_i是0或1。 输入 从标准输入中以以下格式给出输入&#xff1a; A_0A0​ A_1A…...

C++IO流类库

一、输入输出流(I/O strea) 编译系统已经以运算符或函数的形式做好了对标准外设&#xff08;键盘、屏幕、打印机、文件&#xff09;的接口&#xff0c;使用时只需按照要求的格式调用即可。 cin>>x; cout<<x; cin.get(ch); C语言的I/O系统向用户提供一个统一…...

常见的锁策略+synchronized(特性解释)

该篇文章主要是对常见的锁策略的总结&#xff08;主要的作用是扫盲&#xff09;&#xff0c;如想要了解其他部分&#xff0c;这部分可以不用看 目录 一、常见的锁策略1. 悲观锁vs乐观锁举例&#xff1a; 2. 重量级锁vs轻量级锁3. 挂起等待锁vs自旋锁举例 4.普通互斥锁vs读写锁…...

spring打包,打包错误

打包(idea) 通过点击井盖样式的符号可以将test测试类取消打包进去 点击“M”&#xff0c;双击package即可打包 打包出错 ❯ java -jar /home/ying/Documents/java_workspace/spring-01-ioc/target/spring-01-ioc-0.0.1-SNAPSHOT.jar Error: LinkageError occurred while loadi…...

【Linux系统】进程间通信-System V消息队列

&#x1f381;个人主页&#xff1a;我们的五年 &#x1f50d;系列专栏&#xff1a;Linux网络编程 &#x1f337;追光的人&#xff0c;终会万丈光芒 &#x1f389;欢迎大家点赞&#x1f44d;评论&#x1f4dd;收藏⭐文章 ​ Linux网络系列文章计算机网络&#xff08;Linux网…...

DeepSeek×擎创科技:当智能运维遇见大模型「懂行」革命

运维人最懂「动态阈值」的痛 在数字化转型浪潮中&#xff0c;运维监控正经历从"人工经验"到"智能决策"的跃迁。传统动态阈值设置依赖人工分析历史数据、反复调整规则的模式&#xff0c;既难以应对业务波动性&#xff0c;又消耗大量技术资源。 擎创科技基…...

手绘风格流程图工具:简单高效的在线流程图绘制工具

手绘风格流程图&#xff1a;简单高效的在线流程图绘制工具 &#x1f389; 项目介绍 大家好&#xff01;我很高兴向大家分享我最近开发的一个项目 —— 在线绘制手绘风格流程图&#xff0c;这是一个简单高效的在线流程图绘制工具。无论是整理思路、规划项目还是准备演示&#…...

leetcode287.寻找重复数

与寻找链表环的起始点一样 &#xff0c;用快慢指针让二者相遇后&#xff0c;慢指针回到起始点二者以同样速度移动最终会在环的起始点相遇 class Solution {public int findDuplicate(int[] nums) {int slow nums[0], fast nums[0];do {slow nums[slow];fast nums[nums[fas…...

error LNK2019: 无法解析的外部符号 __imp__XXXX,该符号在函数xxxxx中被引用

这个链接错误表明在编译过程中&#xff0c;链接器无法找到 XXXX 函数的实现。以下是解决这个问题的步骤&#xff1a; 可能的原因和解决方案&#xff1a; 函数声明与实现不匹配&#xff1a; 检查 XXXX 函数的声明和实现是否完全一致&#xff08;包括返回类型、参数列表和调用约…...

【LeetCode基础算法】二叉树所有类型

1.遍历二叉树 二叉树的前序遍历二叉树的中序遍历二叉树的后序遍历叶子相似的树 1288 LCP 44. 开幕式焰火左叶子之和 2.自顶向下DFS 二叉树的最大深度二叉树的最小深度路径总和求根节点到叶节点数字之和二叉树的右视图统计二叉树中好节点的数目 1360 3.自底向上 DFS 二叉树…...

AIGC5——AIGC的伦理与法律挑战:数据隐私、真实性危机与版权治理

引言 随着生成式AI&#xff08;AIGC&#xff09;的爆发式增长&#xff0c;其引发的伦理与法律问题日益凸显。从数据隐私泄露到AI幻觉导致的虚假信息&#xff0c;再到训练数据版权争议&#xff0c;AIGC正在挑战现有法律框架与社会信任体系。本文将系统分析三大核心问题&#xf…...

LLM架构解析:词嵌入模型 Word Embeddings(第二部分)—— 从基础原理到实践应用的深度探索

本专栏深入探究从循环神经网络&#xff08;RNN&#xff09;到Transformer等自然语言处理&#xff08;NLP&#xff09;模型的架构&#xff0c;以及基于这些模型构建的应用程序。 本系列文章内容&#xff1a; NLP自然语言处理基础词嵌入&#xff08;Word Embeddings&#xff09…...

marked库(高效将 Markdown 转换为 HTML 的利器)

文章目录 前言使用基本使用自定义渲染器例子 代码高亮 前言 最近尝试了一下通过星火大模型将ai引入到项目上&#xff0c;但是ai返回的数据可以显而易见的发现是markedown语法的&#xff0c;那么就需要一个工具&#xff0c;将类似这种的格式转换为markdown格式 Marked 是一个用…...

Vue3 + Element Plus + AntV X6 实现拖拽树组件

Vue3 Element Plus AntV X6 实现拖拽树组件 介绍 在本篇文章中&#xff0c;我们将介绍如何使用 Vue 3 和 Element Plus 结合 antv/x6 实现树形结构的拖拽功能。用户可以将树节点拖拽到图形区域&#xff0c;自动创建相应的节点。我们将会通过简单的示例来一步步讲解实现过程…...

在 Rocky Linux 9.2 上编译安装 Redis 6.2.6

文章目录 在 Rocky Linux 9.2 上编译安装 Redis 6.2.6Redis 介绍官网Redis 的核心特性高性能支持多种数据结构多种持久化机制复制与高可用2.5 事务与 Lua 脚本消息队列功能 Redis 适用场景Redis 与其他数据库对比Redis 的优势与劣势Redis 优势Redis 劣势 部署过程系统环境信息环…...

中和农信:让金融“活水”精准浇灌乡村沃土

2025年政府工作报告首提“投资于人”概念&#xff0c;并22次提及“金融”&#xff0c;强调要着力抓好“三农”工作&#xff0c;深入推进乡村全面振兴&#xff1b;一体推进地方中小金融机构风险处置和转型发展&#xff1b;扎扎实实落实促进民营经济发展的政策措施&#xff0c;切…...

4. 理解Prompt Engineering:如何让模型听懂你的需求

引言:当模型变成“实习生” 想象一下,你新招的实习生总把“帮我写份报告”理解为“做PPT”或“整理数据表”——这正是开发者与大模型对话的日常困境。某金融公司优化提示词后,合同审查准确率从72%飙升至94%。本文将用3个核心法则+5个行业案例,教你用Prompt Engineering让…...

cocos 图片上传与下载

创建一个场景 在 Cocos Creator 中&#xff0c;我们将从接口获取的图片 URL 列表动态创建图片节点并显示在页面上。使用 assetManager.loadRemote 来加载这些图片并显示。 目录结构如下 为按钮button和文本Lable挂载ts脚本 运行界面 图片上传测试 背景会变成上传的图片 以下是…...

Unity中的UI坐标和点击接口

默认已经知道UI中的基础知识&#xff0c;这里提供一些细节 &#x1f4da;️锚点和轴心点 锚点是根据父物体的确定的&#xff0c;锚点Anchor分为两种状态&#xff0c;Min Max 和 Min ! Max Min ! Max时会根据锚点进行自适应拉伸 参考文章&#xff1a;Unity 锚点 Anchors的通俗…...

基于JavaWeb的二手图书交易系统(源码+lw+部署文档+讲解),源码可白嫖!

摘要 人类现已迈入二十一世纪&#xff0c;科学技术日新月异&#xff0c;经济、资讯等各方面都有了非常大的进步&#xff0c;尤其是资讯与网络技术的飞速发展&#xff0c;对政治、经济、军事、文化等各方面都有了极大的影响。 利用电脑网络的这些便利&#xff0c;发展一套二手图…...