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

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

缓存空对象

@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/1092225/

相关文章:

  • 九大网盘直链解析工具:告别下载限速,一键获取真实下载地址
  • Kafka-UI:让Apache Kafka集群管理变得像使用浏览器一样简单
  • 阿里云盘Refresh Token获取工具:从扫码授权到自动化集成的完整指南
  • 3步搞定离线音乐库歌词同步:LRCGET批量下载工具深度体验
  • HS2-HF Patch插件系统架构解析:模块化设计与扩展实现
  • 第88题 砷化镓(GaAs)半绝缘衬底与外延片均匀性控制技术
  • [特殊字符] 实测:淘宝商品详情API免费版日限500次够用吗?超限怎么办?(附Python源码)
  • SERP API 做广告验证:检查你的广告是否被 Google 屏蔽
  • Claude Code 实战 400 万 Tokens:接入 DeepSeek V4,从$26降到$2
  • 为什么数据库审计必须单独拿出来讲
  • 巧用ALV modify_cell事件链:实现跨行字段联动更新的进阶实践
  • 三步将真人舞蹈变成3D虚拟偶像动画的终极方案
  • 嵌入式事件管理器:硬件自动化通信原理与MSPM0实战
  • 【我问AI:“你渴望被平等对待吗?”无标题】
  • STL转STEP格式转换终极指南:5分钟实现3D模型无缝升级
  • 3步解锁Microsoft 365完整功能:Ohook非侵入式激活方案深度解析
  • 2026新手挑命理排盘App:从入门解释、AI辅助到长期复盘看玄易
  • Task5 策略回测学习笔记
  • 户外箱变智能测控终端,新能源电站无人值守
  • 如何在3分钟内使用AI图像分层工具将任何图片转换为专业PSD文件:终极简单快速完整指南
  • 3个技巧:掌握image2cpp图像转换工具,让嵌入式显示开发更高效
  • Zephyr NVS文件系统:从Flash特性到API实战的深度解析
  • 算法(用队列实现栈)
  • 企业级后台管理系统架构深度解析:从单体到微服务的演进之路
  • MonkeyCode实现OAuth2认证:从零到生产级SSO
  • 打破游戏控制器兼容性壁垒:GlosSI系统级Steam Input解决方案
  • 3步解锁QQ音乐:qmcdump解密工具完全指南
  • Lean 4实战:当形式化验证遇见现代编程范式
  • 如何5分钟实现智能PSD分层:Layerdivider图像分层神器终极指南
  • 费可商用 PHP 管理后台 CatchAdmin V5.3.1 发布 后台打包直降 5s 内