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

什么是缓存穿透、缓存击穿、缓存雪崩?分别如何解决?

Redis 是一个开源的内存数据存储系统广泛应用于缓存、消息队列等场景。尽管 Redis 在高并发环境下十分高效但在使用过程中可能会遇到缓存穿透、缓存击穿和缓存雪崩等问题。本文将详细介绍这三者的概念及其解决方案并通过 Java 代码示例来加深理解。1. 缓存穿透 (Cache Penetration)概念缓存穿透指的是请求一个根本不存在的数据这种请求绕过了缓存直接打到了数据库上。当大量这样的请求涌来时数据库将承受巨大的压力可能导致数据库崩溃。解决方案布隆过滤器可以利用布隆过滤器在缓存前先进行一个存在性检查如果布隆过滤器中没有这个键则直接返回不会查询数据库。返回错误信息对于无效的请求可以在缓存中保存一个特殊的值如 NULL来标识该数据不存在后续请求直接返回缓存中的标识值避免重复查询数据库。Java 示例代码importorg.springframework.data.redis.core.StringRedisTemplate;importorg.springframework.stereotype.Service;ServicepublicclassCacheService{privatefinalStringRedisTemplateredisTemplate;publicCacheService(StringRedisTemplateredisTemplate){this.redisTemplateredisTemplate;}publicObjectgetData(Stringkey){// 检查布隆过滤器if(!isExistsInBloomFilter(key)){returnnull;// 或返回错误信息}// 从缓存中获取数据StringcachedDataredisTemplate.opsForValue().get(key);if(cachedData!null){returncachedData;}// 缓存中不存在查询数据库ObjectdataFromDbqueryDatabase(key);if(dataFromDbnull){// 数据库中也不存在缓存一个特定的值redisTemplate.opsForValue().set(key,NULL);// 缓存空值}else{// 存在则缓存并返回redisTemplate.opsForValue().set(key,dataFromDb.toString());}returndataFromDb;}privatebooleanisExistsInBloomFilter(Stringkey){// 布隆过滤器检查逻辑// ...returntrue;// 示例}privateObjectqueryDatabase(Stringkey){// 数据库查询逻辑// ...returnnull;// 示例}}2. 缓存击穿 (Cache Breakdown)概念缓存击穿是指某个热点数据在缓存过期后恰好有大量请求涌入这些请求直接查询数据库造成数据库瞬间负载增加。解决方案互斥锁在请求处理时使用分布式锁如 Redis 的 SETNX 命令来保证只有一个线程能够去查询数据库其他线程等待查询结果返回后再一次性写入缓存。提前预热在缓存过期之前定期主动更新缓存保持热点数据的可用性。Java 示例代码importorg.springframework.data.redis.core.StringRedisTemplate;importorg.springframework.stereotype.Service;importjava.util.concurrent.TimeUnit;ServicepublicclassCacheService{privatefinalStringRedisTemplateredisTemplate;publicCacheService(StringRedisTemplateredisTemplate){this.redisTemplateredisTemplate;}publicObjectgetData(Stringkey){StringcachedDataredisTemplate.opsForValue().get(key);if(cachedData!null){returncachedData;}// 缓存中不存在尝试获取锁StringlockKeylock:key;booleanisLockredisTemplate.opsForValue().setIfAbsent(lockKey,1,10,TimeUnit.SECONDS);if(isLock){try{// 重新从数据库中加载数据ObjectdataFromDbqueryDatabase(key);if(dataFromDb!null){redisTemplate.opsForValue().set(key,dataFromDb.toString(),60,TimeUnit.SECONDS);}returndataFromDb;}finally{// 释放锁redisTemplate.delete(lockKey);}}else{// 如果获取不到锁可能有其他线程正在查询数据库稍后重试try{Thread.sleep(100);// 等待一段时间再重试}catch(InterruptedExceptione){Thread.currentThread().interrupt();}returngetData(key);// 再次尝试获取}}privateObjectqueryDatabase(Stringkey){// 数据库查询逻辑// ...returnnull;// 示例}}3. 缓存雪崩 (Cache Avalanche)概念缓存雪崩是指缓存系统中大量缓存同时失效导致大量请求直接访问数据库从而造成数据库的压力剧增甚至崩溃。解决方案设置不同的过期时间为了避免缓存同时失效可以为不同的数据设置不同的超时时间增加缓存的随机性。预热机制在系统启动时提前加载热数据到缓存中以确保始终有数据可用。熔断机制在高并发情况下可以使用限流和熔断来保障服务稳定。Java 示例代码importorg.springframework.data.redis.core.StringRedisTemplate;importorg.springframework.stereotype.Service;importjava.util.concurrent.ThreadLocalRandom;importjava.util.concurrent.TimeUnit;ServicepublicclassCacheService{privatefinalStringRedisTemplateredisTemplate;publicCacheService(StringRedisTemplateredisTemplate){this.redisTemplateredisTemplate;}publicObjectgetData(Stringkey){StringcachedDataredisTemplate.opsForValue().get(key);if(cachedData!null){returncachedData;}// 从数据库查询ObjectdataFromDbqueryDatabase(key);if(dataFromDb!null){// 设置随机的过期时间避免雪崩现象intrandomExpireTime60ThreadLocalRandom.current().nextInt(30);// 60~90秒redisTemplate.opsForValue().set(key,dataFromDb.toString(),randomExpireTime,TimeUnit.SECONDS);}returndataFromDb;}privateObjectqueryDatabase(Stringkey){// 数据库查询逻辑// ...returnnull;// 示例}}最后小结下哈缓存穿透、缓存击穿和缓存雪崩是使用缓存所需考虑的重要问题。通过合理的设计和实现这些解决方案可以有效地提升系统的稳定性和性能尤其在应对高并发场景时。希望本文的介绍和代码示例能对理解和实践有所帮助。
http://www.rkmt.cn/news/1371442.html

相关文章:

  • 告别古板前端界面,这个 Github 狂揽 8.1万 Star 的 UI 开源项目,让你 AI 生成的 UI 界面审美直接拉满
  • 基于 Taotoken 构建支持多模型路由的智能写作助手 Agent
  • 通过curl命令直接测试Taotoken各大模型API的响应
  • Taotoken的用量看板如何帮助我们清晰掌握各模型消耗
  • 【MySQL全面教学】MySQL多表查询与JOIN Day6(2026年)
  • 【MySQL全面教学】MySQL聚合函数与分组Day5(2026年)
  • 如何在5分钟内完成SQLite到MySQL数据库迁移:终极转换指南
  • 3步搞定专业显示管理:ColorControl让色彩控制变得如此简单
  • 告别黑屏!手把手教你为OpenEuler 22.03 LTS配置漂亮的XFCE桌面(附LightDM背景修复)
  • 电脑里突然冒出的FNPLicensingService.exe是啥?手把手教你关闭它(附Adobe/CAD/Xshell等软件排查指南)
  • 【高阶用法】视觉校验:利用 Midscene.js 结合 VLM 进行 UI 渲染缺陷检测
  • 【企业级落地】使用 Midscene.js 自动化生成并导出带截图的详尽测试/运行报告
  • 如何用Chat2DB AI SQL助手让数据查询效率提升300%
  • 5步解锁TimesFM:Google时间序列预测模型的完整实战指南
  • ssm大健康老年公寓管理系统(10093)
  • 如何用SMUDebugTool彻底解决AMD Ryzen处理器调试难题
  • 视频压缩怎么压缩更小?盘点2款免费“无损”压缩神器,小白也能学会 - 小有的家
  • 5分钟部署开源翻译工具:让浏览器变身智能翻译助手
  • 跟着 MDN 学CSS day_15:(掌握CSS背景与边框的创造性用法)
  • 如何免费将CAJ文件转换为高质量PDF?caj2pdf完整指南
  • AI Agent Harness Engineering 上下文窗口扩展:长文本理解能力的技术突破
  • 如何在5分钟内用VPKEdit一站式管理20多种游戏资源包格式?
  • Taotoken 用量看板如何帮助个人开发者管理月度成本
  • PotPlayer字幕翻译插件:5步实现免费自动化双语字幕体验
  • 终极指南:如何用PvZ Toolkit彻底改变你的植物大战僵尸体验
  • 别再只用阿里云了!RHEL 9保姆级教程:多源配置、优先级管理与速度测试(清华/中科大/网易源对比)
  • Xenos DLL注入器深度解析:Windows进程内存操控核心技术实现
  • 诈骗分子利用微软内部账户发垃圾链接,微软能否解决安全漏洞?
  • Mermaid在线编辑器:如何用5分钟创建专业级技术图表
  • 独立开发者如何利用 Token Plan 套餐应对项目周期性的用量高峰