一篇文章搞懂缓存问题(上)
一.缓存是什么缓存Cache是计算机系统中一种用于临时存储数据的技术其核心目的是提高数据访问速度和降低后端系统的负载。二.缓存的利与弊1利1.提升响应速度低延迟原理缓存通常基于内存如 Redis访问速度是纳秒/微秒级而数据库通常基于磁盘访问速度是毫秒级。2.保护后端数据库高吞吐原理大部分读请求被缓存拦截只有未命中的请求才会到达数据库。3.降低系统成本原理通过缓存抗住流量可以减少数据库服务器的数量或配置要求。4.削峰填谷原理在突发流量如秒杀活动到来时缓存可以像蓄水池一样吸收大量读请求。5.减少重复计算场景对于复杂的统计报表、AI 推理结果或耗时的 API 调用。2弊1.数据一致性问题最核心痛点问题缓存中的数据是数据库数据的副本。当数据库更新时如果缓存没有及时更新或删除用户就会读到“脏数据”旧数据。难度在高并发场景下保证“数据库”和“缓存”强一致性非常困难且代价高昂通常需要牺牲性能。大多数场景只能做到“最终一致性”。2.增加系统复杂度架构变重引入缓存意味着多了一个组件如 Redis 集群需要维护其高可用、持久化、扩容等。代码变复杂开发人员需要编写额外的逻辑来处理缓存命中、未命中、更新、删除、过期等策略代码出错概率增加。3.经典的“三大坑”如果不加小心缓存会引发三种典型的灾难性故障缓存穿透 (Cache Penetration)查询不存在的数据缓存不存请求直打数据库。恶意攻击者可利用此点搞挂数据库。缓存击穿 (Cache Breakdown)某个热点 Key突然过期此时大量并发请求同时涌入直接击穿缓存打到数据库。缓存雪崩 (Cache Avalanche)大量 Key 同时过期或者缓存服务整体宕机导致所有请求瞬间涌向数据库造成数据库崩溃。4.内存成本与容量限制成本内存比磁盘贵得多。为了获得高性能需要投入更多资金购买大容量内存。限制内存容量有限必须设计合理的淘汰策略如 LRU。如果策略不当可能导致频繁淘汰热点数据降低缓存命中率使缓存形同虚设。5.数据时效性延迟问题为了保证性能通常不会实时同步缓存。这意味着用户看到的数据可能不是最新的例如下单后库存显示未减需等待几秒刷新。影响对于对实时性要求极高的场景如银行余额、股票交易缓存的使用受到严格限制。三.添加缓存1.流程图2.实战应用3.代码实现Service public class ShopServiceImpl extends ServiceImplShopMapper, Shop implements IShopService { Autowired private StringRedisTemplate stringRedisTemplate; Override public Result queryById(Long id) { //从Redis中查询 String shopJson stringRedisTemplate.opsForValue().get(cache:shop: id); //判断是否存在 if (StrUtil.isNotBlank(shopJson)) { Shop shop JSONUtil.toBean(shopJson, Shop.class); return Result.ok(shop); } //不存在根据id查询数据库 Shop shop getById(id); //如果数据库中不存在返回结果 if (shop null) { return Result.fail(店铺不存在); } //存在写入Redis stringRedisTemplate.opsForValue().set(cache:shop: id, JSONUtil.toJsonStr(shop)); return Result.ok(shop); } }Service public class ShopTypeServiceImpl extends ServiceImplShopTypeMapper, ShopType implements IShopTypeService { Autowired private StringRedisTemplate stringRedisTemplate; Override public Result queryTypeList() { //去redis中查询 String shopTypeJson stringRedisTemplate.opsForValue().get(cache:shop:type); //判断是否存在 if (StrUtil.isNotBlank(shopTypeJson)){ ListShopType typeList JSONUtil.toList(shopTypeJson, ShopType.class); return Result.ok(typeList); } //查询数据库 ListShopType typeList query().orderByAsc(sort).list(); //不存在返回错误 if (typeList.isEmpty()) { // 返回成功状态但带上提示信息 return Result.fail(店铺不存在); } //存在写入redis中并返回结果 stringRedisTemplate.opsForValue().set(cache:shop:type, JSONUtil.toJsonStr(typeList)); return Result.ok(typeList); } }四..缓存更新策略1.三种策略根据业务需要选择低一致性方案和高一致性方案。2.主动更新的三种策略1.Cache Aside Pattern由缓存的调用者在更新数据库的同时更新缓存2.Read/Write Through Pattern缓存与数据库整合为一个服务由服务来维护一致性。调用者调用该服务无需关心缓存一致性问题。3.Write Behind Caching Pattern调用者只操作缓存由其它线程异步的将缓存数据持久化到数据库保证最终一致。企业中使用最多的为第一种策略3.操作缓存和数据库中需要考虑的问题操作缓存和数据库时有三个问题需要考虑删除缓存还是更新缓存更新缓存每次更新数据库都更新缓存无效写操作较多 ❌删除缓存更新数据库时让缓存失效查询时再更新缓存 ✅如何保证缓存与数据库的操作的同时成功或失败单体系统将缓存与数据库操作放在一个事务分布式系统利用TCC等分布式事务方案3.先操作缓存还是数据库图中展示的是“先删缓存再更新DB”与“先更新DB再删缓存”的并发问题。前者易导致旧数据被重新写入缓存后者在极端时序下可能使新值被旧查询覆盖。后者的发生频率较低所以我们选择先更新数据库在删除缓存4.代码实现Override public Result update(Shop shop) { Long id shop.getId(); if (id null) { return Result.fail(店铺id不能为空); } //更新数据库 updateById(shop); //删除缓存 stringRedisTemplate.delete(cache:shop: shop.getId()); return Result.ok(); }五.缓存穿透当客户端频繁请求根本不存在的数据如 ID 为 -1 或随机伪造 key由于缓存和数据库中都没有该数据每次请求都会直达数据库造成数据库压力剧增甚至被拖垮。这就是“缓存穿透”。1.缓存空对象即使查询结果为空比如数据库返回 null也把这个“空值”写入缓存并设置一个较短的过期时间TTL如 5 分钟。优点实现简单代码改动小。维护方便无需额外组件。缺点浪费内存大量无效 key 占用 Redis 空间。短期不一致如果数据后来被创建但缓存还在 TTL 内用户仍会读到旧空值。适用场景对一致性要求不高、数据量不大、追求快速上线的场景。2.布隆过滤器在请求到达 Redis 之前先通过布隆过滤器判断这个 key “是否可能存在”。→ 如果过滤器说“不存在”直接拒绝请求→ 如果说“可能存在”才放行去查缓存/数据库。布隆过滤器是概率型数据结构不会漏判false negative但可能误判false positive—— 即它说“有”实际可能没有但它说“没有”那一定没有。优点节省内存不存储真实 key只存哈希位图。无冗余 key避免缓存中堆积大量空值。缺点实现复杂需引入第三方库或自行实现。存在误判少数合法请求可能被错误拦截可通过调整参数降低概率。删除困难标准布隆过滤器不支持删除元素可用计数布隆过滤器解决。适用场景高并发、大数据量、对资源敏感且能接受极低误判率的系统。3.代码实现Override public Result queryById(Long id) { //从Redis中查询 String shopJson stringRedisTemplate.opsForValue().get(cache:shop: id); //判断是否存在 if (StrUtil.isNotBlank(shopJson)) { Shop shop JSONUtil.toBean(shopJson, Shop.class); return Result.ok(shop); } //判断是否为空值 if (shopJson ! null) { return Result.fail(店铺不存在); } //不存在根据id查询数据库 Shop shop getById(id); //如果数据库中不存在返回结果 if (shop null) { //存在写入Redis stringRedisTemplate.opsForValue().set(cache:shop: id, JSONUtil.toJsonStr(shop),30L,TimeUnit.MINUTES); return Result.fail(店铺不存在); } return Result.ok(shop); }增加了两个核心判断第一个是判断是否为空值第二个是如果是空值的话将空值存入redis中六.缓存雪崩缓存雪崩是指在同一时段大量的缓存key同时失效或者Redis服务宕机导致大量请求到达数据库带来巨大压力。解决方案给不同的Key的TTL添加随机值利用Redis集群提高服务的可用性给缓存业务添加降级限流策略给业务添加多级缓存七.缓存击穿缓存击穿是指在一个高并发系统中某个热点 KeyHot Key在缓存中过期失效的瞬间恰好有大量并发请求同时访问该 Key。由于缓存中已无数据所有请求会直接穿透缓存瞬间全部打到后端数据库上。这会导致数据库负载急剧飙升甚至造成数据库宕机进而导致整个系统服务不可用。有两种解决方法一种是互斥锁一种是逻辑过期1.互斥锁vs逻辑过期方案一互斥锁Mutex Lock优点没有额外的内存消耗不需要在缓存值中嵌入额外字段节省空间。保证数据一致性同一时间只有一个线程能重建缓存确保返回给用户的始终是最新数据。实现简单直观基于 Redis 的SETNX或分布式锁框架如 Redisson即可快速落地。缺点线程需要等待性能受影响未抢到锁的请求必须阻塞或轮询重试增加响应延迟。可能存在死锁风险若加锁后异常未释放锁或服务器宕机可能导致后续请求永久阻塞需配合 TTL finally 释放机制规避。方案二逻辑过期Logical Expiration优点线程无需等待性能较好即使缓存“逻辑上”已过期仍立即返回旧数据用户无感知后台异步更新不影响主流程。无死锁风险不依赖阻塞式锁机制彻底避免死锁问题。缺点不保证强一致性在缓存重建完成前部分用户可能读到稍旧的数据最终一致性。有额外内存消耗需在 Value 中存储逻辑过期时间戳略微增加内存占用。实现复杂度高需设计数据结构、管理异步线程池、处理双重检查等开发和维护成本较高。

相关新闻

2026夸克网盘免费扩容1TB空间【亲测可用】

2026夸克网盘免费扩容1TB空间【亲测可用】

如果你平时用夸克网盘存资料、网课或视频,大概率都会被 10G 初始容量卡住。很多人知道“好像能免费扩容”,但真正去操作时却发现:明明照着做了,还是只有 10G;用电脑点了链接,容量没变化还是10gb....&#x…

2026/7/5 21:09:19 阅读更多 →
【ASP.Net MVC 】使用Moq让单元测试变得更简单

【ASP.Net MVC 】使用Moq让单元测试变得更简单

崭坠棕棕1. DATAS(Dynamic Adaptation To Application Sizes) 默认启用:在.NET 9中,DATAS功能已被引入但未默认启用;而在.NET 10中,DATAS将成为默认特性。这对于从旧版本升级到.NET 10的用户来说是一个显著…

2026/7/5 17:01:14 阅读更多 →
深入理解JavaScript系列():揭秘命名函数表达式

深入理解JavaScript系列():揭秘命名函数表达式

诽闹级瓤项目背景 最近在研究 Rokid AR 眼镜的开发,想做点有意思的东西。看了一圈案例,发现大家都在做一些比较"正经"的应用——导航、信息展示之类的。我就想,能不能整点不一样的? 游戏!而且是用语音控制的…

2026/7/7 13:44:10 阅读更多 →

最新新闻

AD5593R与PIC32MZ的混合信号系统设计与实践

AD5593R与PIC32MZ的混合信号系统设计与实践

1. AD5593R与PIC32MZ1024EFK144的硬件协同设计AD5593R这颗芯片最吸引人的地方在于它的多功能引脚配置——8个I/O引脚可以独立配置为12位DAC输出、12位ADC输入、数字输出或数字输入。我在实际项目中经常用它来替代传统的独立ADC和DAC芯片组合,特别是在空间受限的嵌入…

2026/7/7 19:10:38 阅读更多 →
力扣1008:前序重建BST

力扣1008:前序重建BST

力扣 1008 题解析与 C 代码 一、问题解析题目描述:给定一个整数数组 preorder,表示二叉搜索树(BST)的前序遍历结果,请重建该二叉搜索树并返回其根节点。题目保证对于给定的测试用例,总能找到一棵二叉搜索树…

2026/7/7 19:06:38 阅读更多 →
Donau集群环境变量配置指南:SLURM_*变量到Donau的完美转换

Donau集群环境变量配置指南:SLURM_*变量到Donau的完美转换

Donau集群环境变量配置指南:SLURM_*变量到Donau的完美转换 【免费下载链接】donau-slurm-wrappers donau-slurm-wrappers provide some scripts for Slurm Users to submit and manage jobs in Donau cluster environment 项目地址: https://gitcode.com/openeule…

2026/7/7 19:06:37 阅读更多 →
OpenSSL漏洞修复与版本升级:保障系统安全的关键步骤

OpenSSL漏洞修复与版本升级:保障系统安全的关键步骤

OpenSSL漏洞修复与版本升级:保障系统安全的关键步骤 【免费下载链接】openssl 项目地址: https://gitcode.com/openeuler/openssl 前往项目官网免费下载:https://ar.openeuler.org/ar/ OpenSSL作为开源的加密库,广泛应用于各种系统和…

2026/7/7 19:06:37 阅读更多 →
终极鸣潮游戏模组指南:解锁无限游戏体验的完整教程

终极鸣潮游戏模组指南:解锁无限游戏体验的完整教程

终极鸣潮游戏模组指南:解锁无限游戏体验的完整教程 【免费下载链接】wuwa-mod Wuthering Waves pak mods 项目地址: https://gitcode.com/GitHub_Trending/wu/wuwa-mod 还在为《鸣潮》游戏中的技能冷却、体力限制和繁琐操作而烦恼吗?WuWa-Mod作为…

2026/7/7 19:06:37 阅读更多 →
物联网Node-Red开发教程-第2章工作界面与流程基础

物联网Node-Red开发教程-第2章工作界面与流程基础

第2章 工作界面与流程基础 学习目标 熟悉 Node-RED 编辑器的四大区域布局 独立完成第一个 Hello World 流程 深入理解消息对象 msg 的结构和属性 掌握节点端口与连线的规则 学会流程的导入导出和日常管理操作 2.1 编辑器布局 Node-RED 的编辑器是一个基于 Web 的界面,打开 ht…

2026/7/7 19:04:37 阅读更多 →

日新闻

鸿蒙新特性:图片画廊与轮播导航——构建沉浸式图片浏览体验

鸿蒙新特性:图片画廊与轮播导航——构建沉浸式图片浏览体验

图片浏览是移动应用中最高频的场景之一。从社交应用的照片流到电商平台的商品图集,从旅游应用的景点相册到摄影作品展示——用户对图片浏览的体验要求不断提高:流畅的切换动画、直观的缩略图导航、便捷的收藏操作、自动播放模式。HarmonyOS NEXT ArkUI 虽…

2026/7/7 0:05:16 阅读更多 →
24V DC-DC降压芯片PW2312B/PW2815,SOT23-6到SOP8-EP方案对比

24V DC-DC降压芯片PW2312B/PW2815,SOT23-6到SOP8-EP方案对比

24V稳压芯片完整选型指南 PW8600 PW75XX PW2815 PW2312B LDODC/DC全方案 一、24V稳压方案概述 24V直流电源在工业自动化、门禁系统、电梯控制、汽车电子、LED驱动、监控设备等场景中应用极广,是最常见的中压直流母线电压。要将24V母线稳定降压至下游MCU、传感器…

2026/7/7 0:05:16 阅读更多 →
RAG+知识图谱混合检索与Graph RAG核心对比

RAG+知识图谱混合检索与Graph RAG核心对比

做企业RAG落地的团队,往往容易卡在一容易踩坑的选型难题: 当需求单纯靠向量RAG搞不定、单纯靠知识图谱也搞不定,必须同时依赖「文本语义理解 实体关系推理」时,到底是做「向量图谱混合检索」就够了,还是必须上「Grap…

2026/7/7 0:07:19 阅读更多 →

周新闻

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容 【免费下载链接】BiliTools A cross-platform bilibili toolbox. 跨平台哔哩哔哩工具箱,支持下载视频、番剧等等各类资源 项目地址: https://gitcode.com/GitHub_Trending/bilit/BiliTools …

2026/7/7 14:24:45 阅读更多 →
威胁模型全解析:从新手入门到实战应用,助你构建安全产品!

威胁模型全解析:从新手入门到实战应用,助你构建安全产品!

威胁模型的陌生现状在忙碌疲惫的一天里,参与了关于混合后量子密码学的讨论,应付端点攻击找茬的人,还参与留言板讨论后,发现“威胁模型”对多数人仍是陌生概念,且多被当作时髦用语。有趣的相关画作有一幅由 Embyr 创作的…

2026/7/7 12:34:47 阅读更多 →
渗透测试入门指南:从零基础到实战环境搭建

渗透测试入门指南:从零基础到实战环境搭建

1. 从“看热闹”到“入门”:我理解的渗透测试到底是什么?每次看到新闻里说某个大公司的数据被“黑”了,或者某个网站被攻击导致服务瘫痪,你是不是和我一样,心里会冒出两个念头:一是“这黑客真厉害”&#x…

2026/7/7 15:59:06 阅读更多 →

月新闻