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

Redis缓存实战:彻底解决缓存穿透、击穿、雪崩三大难题

一、缓存穿透

问题描述

查询一个数据库和缓存中都不存在的key,每次请求都打到数据库,大量请求可能拖垃数据库。

解决方案

1. 缓存空对象

@Service public class UserService { @Autowired private RedisTemplate<String, Object> redisTemplate; @Autowired private UserMapper userMapper; public User getUserById(Long id) { String key = "user:" + id; // 查询缓存 User user = (User) redisTemplate.opsForValue().get(key); if (user != null) { return user.getId() == null ? null : user; // 返回空对象表示不存在 } // 查询数据库 user = userMapper.selectById(id); if (user == null) { // 缓存空对象,设置短过期时间 redisTemplate.opsForValue().set(key, new User(), 5, TimeUnit.MINUTES); return null; } redisTemplate.opsForValue().set(key, user, 30, TimeUnit.MINUTES); return user; } }

2. 布隆过滤器:将所有合法key存入Bloom Filter,请求先过滤器,不存在的key直接拖到。

回到顶部

二、缓存击穿

问题描述

查询一个缓存刚好失效的key,大量请求同时打到数据库。

解决方案

互斥锁(推荐)

public User getUserById(Long id) { String key = "user:" + id; User user = (User) redisTemplate.opsForValue().get(key); if (user != null) return user; // 加分布式锁 String lockKey = "lock:user:" + id; Boolean locked = redisTemplate.opsForValue() .setIfAbsent(lockKey, "1", 10, TimeUnit.SECONDS); if (Boolean.TRUE.equals(locked)) { try { // 再次查询缓存(可能其他线程已经写入) user = (User) redisTemplate.opsForValue().get(key); if (user == null) { user = userMapper.selectById(id); redisTemplate.opsForValue().set(key, user, 30, TimeUnit.MINUTES); } } finally { redisTemplate.delete(lockKey); } } else { // 未获得锁,稍等重试 Thread.sleep(50); return getUserById(id); } return user; }

回到顶部

三、缓存雪崩

问题描述

大量缓存key同时失效,大量请求同时打到数据库。

解决方案

1. 过期时间加随机偶数

// 设置缓存时加随机偶数,避免同时失效 int randomExpire = 30 + new Random().nextInt(10); // 30~40分钟 redisTemplate.opsForValue().set(key, user, randomExpire, TimeUnit.MINUTES);

2. 多级缓存:本地缓存(Caffeine)+ Redis两级,即使 Redis雪崩也有本地缓存托底。

3. 缓存预热:项目启动时提前将热点数据加载到缓存。

回到顶部

总结

问题原因解决方案
缓存穿透key不存在空对象 / 布隆过滤器
缓存击穿key失效瞬间互斥锁 / 逆机制
缓存雪崩大量同时失效随机过期 / 多级缓存
http://www.jsqmd.com/news/1099636/

相关文章:

  • 软件工程从业所需的技能:正确认识行业,并走出可持续的职业生涯
  • 整群随机抽样
  • 可视化学科发展脉络浅梳(学习笔记)
  • 京东开源实时视频视觉语言交互模型:全栈方案解析与落地实践
  • sdfsfds
  • 2026 年本地部署的 AI 数字人直播系统到底有多省钱?
  • 开源模型技术总结-3————FireRed(小红书)开源模型
  • 北京心商科技发布GEO优化产品 助力企业合规营销
  • 从Prompt到Loop,拆解Agent 进化的底层逻辑
  • Agent推理快到API成瓶颈:Responses API WebSocket如何提速40%
  • 51单片机数码管电压表
  • 大模型评测与AI产品质量保障:第3篇 用 Python 调用 模型API
  • OpenAI SDK 环境搭建教程
  • Xshell+Xftp使用教程
  • 主流三维光学轮廓仪国产品牌与技术解析
  • 操作简便吗?8款AI写作辅助网站综合榜,毕业答辩稳了!
  • TactiX实测:星际2战术训练神器,支持离线REP解析与MOD扩展
  • 2026 在上海如何找一家专业又靠谱的小程序定制开发公司
  • 告别命令行!用JGit在Java项目里优雅地操作Git(附完整API使用示例)
  • SpringBoot(springboot的类加载和传统的双亲委派有什么区别、如何按顺序实例化Bean)
  • 】[SampleVirtualTexture节点]原理解析与实际应用
  • 只看光明的一面:当机器学习失去“反面教材“时 | Positive-Only Learning深度解读
  • MySQL8-Windows安装教程
  • 【第 8 篇:数据接口管理——从模拟到真实与企业级接口治理】
  • 2026最新年版Java八股文,7天背完通过面试
  • 2026亚太EMBA QS排名客观测评与科学择校指南
  • 机器人电源方案评审清单:别只看电压电流,还要看这 6 件事
  • 3步掌握Windows安卓应用安装:APK Installer跨平台革命
  • Three.js 轨道控制器教程
  • 量子态制备的哈密顿量框架与硬件优化实践