尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
Redis 缓存实战:雪崩、穿透、击穿一次讲透
缓存用好了是性能翻倍用不好凌晨三点把你叫醒。Redis 在大多数系统里扮演的角色是挡在数据库前面的一堵墙。正常情况下请求打到 Redis命中就走数据库压力不大。但这堵墙有三个洞它可能整堵墙同时塌可能有人绕过墙直接锤数据库也可能墙上最忙的那块砖碎了。对应过来就是雪崩、穿透、击穿。一个一个说。一、缓存雪崩整堵墙同时塌了什么是雪崩大量缓存在同一个时间点集中过期所有请求瞬间穿透到数据库数据库扛不住直接挂。典型的触发场景你批量导入了 10 万条商品数据所有缓存都设了 24 小时过期。24 小时后10 万个 key 在同一秒集体死亡。下一秒打进来的请求全部查库数据库连接池瞬间打满。怎么解决三道防线// 防线一过期时间加随机值错开集体死亡 // 不要这样 redisTemplate.opsForValue().set(productKey, value, 24, TimeUnit.HOURS); // 改成这样随机加 1-6 小时 int randomHours ThreadLocalRandom.current().nextInt(1, 7); redisTemplate.opsForValue().set(productKey, value, 24 randomHours, TimeUnit.HOURS); // 防线二永不过期 异步更新 // 缓存本身不设过期由定时任务定期刷新 Scheduled(fixedDelay 300000) // 每5分钟 public void refreshHotProducts() { ListProduct hotProducts productService.getHotProducts(); for (Product p : hotProducts) { String key product: p.getId(); redisTemplate.opsForValue().set(key, p, Duration.ofDays(7)); } } // 注意这里设了7天兜底防止定时任务挂了缓存永远不更新 // 防线三多级缓存 限流兜底 // 如果 Redis 也挂了本地缓存拦截一波 Cacheable(value product, key #id, unless #result null) public Product getProduct(Long id) { return productMapper.selectById(id); } // 数据库层加限流即使被打穿也不至于雪崩到宕机 // Sentinel / RateLimiter 随便选一个核心是保住数据库不挂雪崩的核心矛盾不是数据过期是所有东西同时过期。错开时间就消解了 80% 的风险。二、缓存穿透有人绕过墙直接锤数据库什么是穿透查询一个不存在的数据——缓存里没有数据库里也没有。正常逻辑会直接查库然后发现是空的不写缓存。下次同样的非法请求再来继续查库。恶意攻击者可以构造一大堆不存在的 ID把你的数据库活活打死。// 漏洞代码 public Product getProduct(Long id) { String key product: id; Product p (Product) redisTemplate.opsForValue().get(key); if (p ! null) { return p; } p productMapper.selectById(id); if (p ! null) { redisTemplate.opsForValue().set(key, p, 24, TimeUnit.HOURS); } // BUGp 是 null 的时候什么都不做下次还查库 return p; }怎么修// 方案一缓存空值把「没有」也存起来 public Product getProduct(Long id) { String key product: id; Product p (Product) redisTemplate.opsForValue().get(key); if (p ! null) { // 判断是不是空值标记 if (p.getId() -1L) return null; return p; } p productMapper.selectById(id); if (p null) { // 缓存一个空对象短过期防止被恶意刷 Product empty new Product(); empty.setId(-1L); redisTemplate.opsForValue().set(key, empty, 5, TimeUnit.MINUTES); return null; } redisTemplate.opsForValue().set(key, p, 24, TimeUnit.HOURS); return p; }空值缓存的问题是如果有人刷几百万个不同的非法 IDRedis 内存会被空对象占满。所以// 方案二布隆过滤器事前拦截不存在的 key // 用 Guava 或 Redisson 的布隆过滤器 RBloomFilterString bloomFilter redissonClient.getBloomFilter(product_filter); bloomFilter.tryInit(1000000L, 0.01); // 100万容量1%误判率 // 数据写入时同步加入过滤器 bloomFilter.add(product: id); // 查询前先过过滤器 public Product getProduct(Long id) { String key product: id; if (!bloomFilter.contains(key)) { return null; // 一定不存在直接返回不查库 } // 剩下走正常缓存逻辑 // ... }布隆过滤器的代价有 1% 误判率说存在但实际不存在。多查一次数据库是能接受的。它的价值是拦住 99% 的恶意穿透请求。推荐组合布隆过滤器前置拦截 空值缓存兜底。布隆过滤器拦不住的那 1% 由空值缓存接住。三、缓存击穿墙上最忙的那块砖碎了什么是击穿一个热点 key 过期了这个 key 平时扛几万 QPS。过期瞬间几万请求同时打向数据库。和雪崩的区别是雪崩是一大片 key 同时过期击穿是单个爆款 key 过期。典型场景秒杀商品的库存缓存、首页推荐位的配置缓存、大 V 的粉丝数缓存。// 漏洞代码 public Product getHotProduct(Long id) { String key product: id; Product p (Product) redisTemplate.opsForValue().get(key); if (p null) { // 缓存过期了直接查库 // 几千个线程同时走到这里全部查库 p productMapper.selectById(id); redisTemplate.opsForValue().set(key, p, 10, TimeUnit.MINUTES); } return p; }怎么修// 方案一互斥锁只让一个人去查库 public Product getHotProduct(Long id) { String key product: id; String lockKey lock:product: id; Product p (Product) redisTemplate.opsForValue().get(key); if (p ! null) return p; // SET NX EX抢锁超时 10 秒防止死锁 Boolean locked redisTemplate.opsForValue() .setIfAbsent(lockKey, 1, 10, TimeUnit.SECONDS); if (Boolean.TRUE.equals(locked)) { try { // 抢到锁二次检查 p (Product) redisTemplate.opsForValue().get(key); if (p ! null) return p; p productMapper.selectById(id); redisTemplate.opsForValue().set(key, p, 10, TimeUnit.MINUTES); return p; } finally { redisTemplate.delete(lockKey); } } else { // 没抢到锁等 50ms 重试 try { Thread.sleep(50); } catch (InterruptedException ignored) {} return getHotProduct(id); // 递归重试 } } // 方案二逻辑过期不删 key只更新 value // 适合容忍短期旧数据的场景 public Product getHotProductV2(Long id) { String key product: id; Product p (Product) redisTemplate.opsForValue().get(key); if (p null) { // 首次加载 p productMapper.selectById(id); redisTemplate.opsForValue().set(key, p, 10, TimeUnit.MINUTES); return p; } // 判断是否逻辑过期在 value 里塞一个过期时间戳 if (p.getExpireTime() System.currentTimeMillis()) { // 异步更新当前请求直接返回旧数据 threadPool.submit(() - refreshCache(id)); } return p; // 返回可能过期的旧数据但不会击穿 }逻辑过期方案的关键取舍宁愿用户看到 30 秒前的旧数据也别让他等 5 秒白屏。区别速查表类型现象本质核心解法雪崩大量 key 同时过期过期时间一致随机 TTL 永不过期异步刷新穿透查不存在的 key无缓存屏障布隆过滤器 缓存空值击穿单个热点 key 过期高并发查同一个互斥锁 逻辑过期最后不管你用不用 Redis这三类问题本质上都是同一件事当缓存和数据库之间的假设破裂时你的系统有没有兜底。一个缓存 key 过期了你没有互斥锁说明你假设了缓存永远能命中。缓存不存在你没有布隆过滤器说明你假设了所有请求都是合法的。大量 key 同时过期你没有随机 TTL说明你假设了过期时间是均匀分布的。假设被打破的那一刻就是你的系统开始雪崩的那一刻。
RELATED

相关推荐

计算机组成原理-实验三:从零搭建6116 SRAM读写时序与电路分析

计算机组成原理-实验三:从零搭建6116 SRAM读写时序与电路分析

1. 6116 SRAM芯片基础认知第一次拿到6116这颗芯片时,我盯着24个引脚发了半天呆。作为经典的2K8位静态随机存储器,它就像个微型仓库——能存放2048个8位二进制数。与动态DRAM不同,SRAM不需要刷新电路,这让硬件设计简单不少&#xf…

📅 2026/8/23 7:53:18
MATLAB三阶MRAC控制器实现:wl.m脚本含模型跟踪、参数自调与响应可视化

MATLAB三阶MRAC控制器实现:wl.m脚本含模型跟踪、参数自调与响应可视化

本文还有配套的精品资源,点击获取 简介:直接运行wl.m就能跑通一个完整的三阶模型参考自适应控制(MRAC)仿真流程,不需要任何额外工具箱。脚本内部集成了三阶参考模型、被控对象动态方程和基于梯度法的自适应律&#…

📅 2026/8/23 7:53:18
C28x DSP平台三相电机SVPWM实时控制代码包(含扇区判断、死区补偿与ePWM适配)

C28x DSP平台三相电机SVPWM实时控制代码包(含扇区判断、死区补偿与ePWM适配)

本文还有配套的精品资源,点击获取 简介:直接用于TI C28x系列DSP(如TMS320F2812、F28335)的三相电机SVPWM生成代码,核心为SVPWM.c文件,纯软件实现空间矢量脉宽调制算法,不依赖外部专用芯片。支…

📅 2026/9/7 3:19:23
MORE NEWS

更多资讯

📰

Win11Debloat:3 分钟免费拆掉 Windows 11 的预装臃肿和广告

Win11Debloat:3 分钟免费拆掉 Windows 11 的预装臃肿和广告 【免费下载链接】Win11Debloat A simple, lightweight PowerShell script that allows you to remove pre-installed apps, disable telemetry, as well as perform various other changes to declutter a…

📰

水稻田杂草检测数据集:YOLO+VOC双格式1373张标注图像

简介:本资源是面向农业AI与计算机视觉初学者的水稻田杂草目标检测专用数据集,适用于YOLO系列及VOC格式模型的训练与验证,助力智慧农业场景下的作物-杂草识别算法开发。压缩包共2000个文件,含1373张高清原始图像(JPEGIm…

📰

Win11Debloat 完整指南:免费一键移除预装应用、关闭遥测,三步完成 Windows 11 瘦身

Win11Debloat 完整指南:免费一键移除预装应用、关闭遥测,三步完成 Windows 11 瘦身 【免费下载链接】Win11Debloat A simple, lightweight PowerShell script that allows you to remove pre-installed apps, disable telemetry, as well as perform var…

📰

Duix.Avatar 数字人本地部署指南:4 步跑通离线克隆与口播视频生成

Duix.Avatar 数字人本地部署指南:4 步跑通离线克隆与口播视频生成 【免费下载链接】Duix-Avatar 🚀 Truly open-source AI avatar(digital human) toolkit for offline video generation and digital human cloning. 项目地址: https://gitcode.com/Gi…

📰

Midscene.js 完整教程:用自然语言驱动 AI 自动化测试浏览器与手机

Midscene.js 完整教程:用自然语言驱动 AI 自动化测试浏览器与手机 【免费下载链接】midscene GUI Agent for E2E Testing 项目地址: https://gitcode.com/GitHub_Trending/mid/midscene 每次前端重构一次,测试脚本就跟着崩一次?选择器…

📰

FOC无感电机控制工程实战:坐标变换、SVPWM与电流环调参

简介:这是一套面向嵌入式开发者的FOC电机控制算法源码工程,覆盖单电压闭环与电压电流双闭环两种实现方案。资源围绕磁场定向控制原理,包含Clarke/Park变换、PID调节、SVPWM调制等核心模块,并针对有传感器与无传感器FOC的差异、电流…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬