当前位置: 首页 > 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.gsyq.cn/news/1604186.html

相关文章:

  • 阿里云盘Refresh Token获取工具:从扫码授权到自动化集成的完整指南
  • HS2-HF Patch插件系统架构解析:模块化设计与扩展实现
  • 3步搞定离线音乐库歌词同步:LRCGET批量下载工具深度体验
  • 为什么数据库审计必须单独拿出来讲
  • 巧用ALV modify_cell事件链:实现跨行字段联动更新的进阶实践
  • 【我问AI:“你渴望被平等对待吗?”无标题】
  • 3个技巧:掌握image2cpp图像转换工具,让嵌入式显示开发更高效
  • Zephyr NVS文件系统:从Flash特性到API实战的深度解析
  • MonkeyCode实现OAuth2认证:从零到生产级SSO
  • 级别的AutoBuilder,一键干掉80%的重复CRUD工作
  • 费可商用 PHP 管理后台 CatchAdmin V5.3.1 发布 后台打包直降 5s 内
  • 高校汉服租赁网站源码 Java+SpringBoot+Vue 万字文档
  • FDE标准:FDE落地最后一公里,在银行、政务,石油,电力,金融的产品、标准和落地案例
  • IEC 60205-2026
  • 竣宝潜龙尾盘副选精准抓主力洗盘尾巴主升浪信号 九点智投三步点金,五星智投双紫擒龙指标选股魔方量化指标公式
  • item0(1):接地
  • 最新小学生学习前端vue 多插图
  • AMAT 0100-1200印刷电路板
  • WinUtil:革命性Windows系统管理工具,一键完成软件部署与系统优化
  • AutoUnipus终极指南:快速掌握U校园智能刷课工具完整教程
  • 告别图片!三种 CSS 原生方案实现任意方向三角形
  • leetcode:两个数组的交集
  • MouseTester:免费开源的鼠标性能终极测试工具
  • 从工具函数中注入消息
  • 二维数组知识
  • 3D Web 服务器环境搭建
  • 为什么你用光模块测试FPGA IBERT不通
  • AI插件开发实战:基于JS脚本的Illustrator色标生成器设计与实现
  • 特殊上位机权限管理方案
  • 三角洲S10裂变新赛季上线[特殊字符]Mac玩家再也不用错过核电站新图!