【JAVA架构师成长之路】【Redis】第14集:Redis缓存穿透原理、规避、解决方案

30分钟自学教程:Redis缓存穿透原理与解决方案

目标

  1. 理解缓存穿透的成因及危害。
  2. 掌握布隆过滤器、空值缓存等核心防御技术。
  3. 能够通过代码实现请求拦截与缓存保护。
  4. 学会限流降级、异步加载等应急方案。

教程内容

0~2分钟:缓存穿透的定义与核心原因
  • 定义:恶意或异常请求频繁访问数据库中不存在的数据,绕过缓存直接冲击数据库。
  • 典型场景
    • 攻击者伪造大量非法ID(如负数、超长字符串)。
    • 业务未对查询参数校验,或未缓存空结果。
  • 危害
    • 数据库压力激增,甚至宕机。
    • 正常服务被恶意请求拖垮。

2~5分钟:代码模拟穿透场景(Java示例)
// 未做防护的查询方法(模拟穿透问题)  
public Product getProduct(String id) {  String key = "product:" + id;  Product product = redisTemplate.opsForValue().get(key);  if (product == null) {  // 直接查询数据库(未缓存空值)  product = productService.loadFromDB(id);  if (product != null) {  redisTemplate.opsForValue().set(key, product, 1, TimeUnit.HOURS);  }  }  return product; // 恶意请求会反复查询数据库  
}  

验证问题

  • 使用JMeter发送100次id=-1的请求,观察数据库查询次数是否为100次(穿透发生)。

5~12分钟:解决方案1——布隆过滤器(Bloom Filter)
  • 原理:基于位数组和哈希函数,快速判断数据是否可能存在于数据库,拦截非法请求。
  • 代码实现(Redisson布隆过滤器)
// 初始化布隆过滤器并预热合法数据  
public class BloomFilterInit {  private RBloomFilter<String> bloomFilter;  @PostConstruct  public void init() {  bloomFilter = redissonClient.getBloomFilter("product_bloom");  bloomFilter.tryInit(100000L, 0.01); // 容量10万,误判率1%  List<String> validIds = productService.getAllValidIds();  validIds.forEach(bloomFilter::add);  }  
}  // 查询时拦截非法请求  
public Product getProductWithBloomFilter(String id) {  if (!bloomFilter.contains(id)) {  return null; // 直接拦截  }  // 正常查询逻辑...  
}  
  • 注意事项
    • 误判率需根据业务容忍度调整(如0.1%更严格,但占用更多内存)。
    • 需定期同步布隆过滤器与数据库的合法数据(如定时任务)。

12~20分钟:解决方案2——空值缓存(Cache Null)
  • 原理:即使数据库不存在该数据,也缓存空值(如“NULL”),避免重复穿透。
  • 代码实现
public Product getProductWithNullCache(String id) {  String key = "product:" + id;  Product product = redisTemplate.opsForValue().get(key);  if (product == null) {  product = productService.loadFromDB(id);  if (product == null) {  // 缓存空值,5分钟过期  redisTemplate.opsForValue().set(key, "NULL", 5, TimeUnit.MINUTES);  return null;  }  redisTemplate.opsForValue().set(key, product, 1, TimeUnit.HOURS);  } else if ("NULL".equals(product)) {  return null; // 直接返回空结果  }  return product;  
}  
  • 优化点
    • 空值过期时间不宜过长(避免存储大量无效Key)。
    • 可结合布隆过滤器,减少空值缓存的数量。

20~25分钟:解决方案3——请求参数校验
  • 原理:在业务层拦截非法参数(如非数字ID、越界值)。
  • 代码实现(Spring Boot参数校验)
public Product getProduct(@PathVariable String id) {  // 校验ID格式(仅允许数字)  if (!id.matches("\\d+")) {  throw new IllegalArgumentException("非法ID格式");  }  // 校验ID范围(如大于0)  long numericId = Long.parseLong(id);  if (numericId <= 0) {  throw new IllegalArgumentException("ID必须为正数");  }  // 正常查询逻辑...  
}  
  • 扩展
    • 使用Hibernate Validator实现注解式校验(如@Min(1))。

25~28分钟:应急处理方案
  1. 限流降级(Guava RateLimiter)
private RateLimiter rateLimiter = RateLimiter.create(100); // 每秒100个请求  public Product getProduct(String id) {  if (!rateLimiter.tryAcquire()) {  throw new RuntimeException("请求过于频繁,请稍后重试");  }  // 正常查询逻辑...  
}  
  1. 异步加载(CompletableFuture)
public Product getProductAsync(String id) {  String key = "product:" + id;  Product product = redisTemplate.opsForValue().get(key);  if (product == null) {  CompletableFuture.runAsync(() -> {  Product dbProduct = productService.loadFromDB(id);  if (dbProduct != null) {  redisTemplate.opsForValue().set(key, dbProduct, 1, TimeUnit.HOURS);  }  });  }  return product; // 可能返回空,但避免阻塞请求  
}  

28~30分钟:总结与优化方向
  • 核心原则:拦截非法请求、缓存空值、业务兜底。
  • 高级优化
    • 结合Redis Module的RedisBloom扩展(生产级布隆过滤器)。
    • 动态调整限流阈值(如根据数据库负载自动限流)。

练习与拓展

练习

  1. 实现一个布隆过滤器,拦截id<=0的非法请求。
  2. 修改空值缓存逻辑,动态设置随机过期时间(如5~15分钟)。

推荐拓展

  1. 学习RedisBloom模块的安装与使用。
  2. 研究分布式限流框架(如Sentinel)的实现原理。
  3. 探索缓存穿透与缓存击穿的综合防护方案。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/71589.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

尚硅谷爬虫note15

一、当当网 1. 保存数据 数据交给pipelines保存 items中的类名&#xff1a; DemoNddwItem class DemoNddwItem(scrapy.Item): 变量名 类名&#xff08;&#xff09; book DemoNddwItem(src src, name name, price price)导入&#xff1a; from 项目名.items import 类…

LVGL直接解码png图片的方法

通过把png文件解码为.C文件&#xff0c;再放到工程中的供使用&#xff0c;这种方式随时速度快&#xff08;应为已经解码&#xff0c;代码中只要直接加载图片数据显示出来即可&#xff09;&#xff0c;但是不够灵活&#xff0c;适用于哪些简单又不经常需要更换UI的场景下使用。如…

【计算机网络】Socket

Socket 是网络通信的核心技术之一&#xff0c;充当应用程序与网络协议栈之间的接口。 1. Socket 定义 Socket&#xff08;套接字&#xff09;是操作系统提供的 网络通信抽象层&#xff0c;允许应用程序通过标准接口&#xff08;如 TCP/IP 或 UDP&#xff09;进行数据传输。它…

Apache XTable:在数据湖仓一体中推进数据互作性

Apache XTable 通过以多种开放表格式提供对数据的访问&#xff0c;在增强互作性方面迈出了一大步。移动数据很困难&#xff0c;在过去&#xff0c;这意味着在为数据湖仓一体选择开放表格式时&#xff0c;您被锁定在该选择中。一个令人兴奋的项目当在数据堆栈的这一层引入互作性…

anolis8.9-k8s1.32-node-二进制部署

一、系统 # cat /etc/anolis-release Anolis OS release 8.9 # uname -r 5.10.134-18.an8.x86_64 二、从master上拷贝dockers及cri-docker相关文件 # groupadd docker # mkdir /etc/docker# scp -P 4033 root192.168.7.201:/etc/systemd/system/containerd.service /etc/s…

《AJAX:前端异步交互的魔法指南》

什么是AJAX AJAX&#xff08;Asynchronous JavaScript and XML&#xff0c;异步 JavaScript 和 XML&#xff09; 是一种用于创建异步网页应用的技术&#xff0c;允许网页在不重新加载整个页面的情况下&#xff0c;与服务器交换数据并局部更新页面内容。尽管名称中包含 XML&…

Python 性能优化:从入门到精通的实用指南

Langchain系列文章目录 01-玩转LangChain&#xff1a;从模型调用到Prompt模板与输出解析的完整指南 02-玩转 LangChain Memory 模块&#xff1a;四种记忆类型详解及应用场景全覆盖 03-全面掌握 LangChain&#xff1a;从核心链条构建到动态任务分配的实战指南 04-玩转 LangChai…

利用 requestrepo 工具验证 XML外部实体注入漏洞

1. 前言 在数字化浪潮席卷的当下&#xff0c;网络安全的重要性愈发凸显。应用程序在便捷生活与工作的同时&#xff0c;也可能暗藏安全风险。XXE&#xff08;XML外部实体&#xff09;漏洞作为其中的典型代表&#xff0c;攻击者一旦利用它&#xff0c;便能窃取敏感信息、掌控服务…

FreeRTOS第17篇:FreeRTOS链表实现细节05_MiniListItem_t:FreeRTOS内存优化

文/指尖动听知识库-星愿 文章为付费内容,商业行为,禁止私自转载及抄袭,违者必究!!! 文章专栏:深入FreeRTOS内核:从原理到实战的嵌入式开发指南 1 为什么需要迷你列表项? 在嵌入式系统中,内存资源极其宝贵。FreeRTOS为满足不同场景需求,设计了标准列表项(ListItem_…

Spring 无法解决循环依赖的 5 种场景

一、构造器注入引发的循环依赖 1. 问题复现 Component public class ServiceA {private final ServiceB serviceB;Autowiredpublic ServiceA(ServiceB serviceB) { // 构造器注入this.serviceB serviceB;} }Component public class ServiceB {private final ServiceA servic…

Core Vision Kit(基础视觉服务)

文章目录 一、Core Vision Kit简介场景介绍约束与限制二、通用文字识别三、人脸检测一、Core Vision Kit简介 Core Vision Kit(基础视觉服务)是机器视觉相关的基础能力,例如通用文字识别(即OCR,Optical Character Recognition,也称为光学字符识别)、人脸检测、人脸比对…

第TR3周:Pytorch复现Transformer

&#x1f368; 本文为&#x1f517;365天深度学习训练营中的学习记录博客 &#x1f356; 原作者&#xff1a;K同学啊 Transformer通过自注意力机制&#xff0c;改变了序列建模的方式&#xff0c;成为AI领域的基础架构 编码器&#xff1a;理解输入&#xff0c;提取上下文特征…

FreeRTOS 任务间通信机制:队列、信号量、事件标志组详解与实验

1. FreeRTOS 消息队列 1.1 简介 ​ 队列是 任务间通信的主要形式&#xff0c;可用于在任务之间以及中断与任务之间传递消息。队列在 FreeRTOS 中具有以下关键特点&#xff1a; 队列默认采用 先进先出 FIFO 方式&#xff0c;也可以使用 xQueueSendToFront()实现 LIFO。FreeRT…

【虚拟化】Docker Desktop 架构简介

在阅读前您需要了解 docker 架构&#xff1a;Docker architecture WSL 技术&#xff1a;什么是 WSL 2 1.Hyper-V backend 我们知道&#xff0c;Docker Desktop 最开始的架构的后端是采用的 Hyper-V。 Docker daemon (dockerd) 运行在一个 Linux distro (LinuxKit build) 中&…

Unity光照之Halo组件

简介 Halo 组件 是一种用于在游戏中创建光晕效果的工具&#xff0c;主要用于模拟光源周围的发光区域&#xff08;如太阳、灯泡等&#xff09;或物体表面的光线反射扩散效果。 核心功能 1.光晕生成 Halo 组件会在光源或物体的周围生成一个圆形光晕&#xff0c;模拟光线在空气…

Flink深入浅出之01:应用场景、基本架构、部署模式

Flink 1️⃣ 一 、知识要点 &#x1f4d6; 1. Flink简介 Apache Flink — Stateful Computations over Data StreamsApache Flink 是一个分布式大数据处理引擎&#xff0c;可对有界数据流和无界数据流进行有状态的计算。Flink 能在所有常见集群环境中运行&#xff0c;并能以…

2025年【高压电工】报名考试及高压电工考试总结

随着电力行业的快速发展&#xff0c;高压电工成为确保电力系统安全稳定运行的重要一环。为了提高高压电工的专业技能和安全意识&#xff0c;“安全生产模拟考试一点通”平台特别整理了2025年高压电工报名考试的相关信息及考试总结&#xff0c;并提供了一套完整的题库&#xff0…

网络HTTP

HTTP Network Request Library A Retrofit-based HTTP network request encapsulation library that provides simple and easy-to-use API interfaces with complete network request functionality. 基于Retrofit的HTTP网络请求封装库&#xff0c;提供简单易用的API接口和完…

os-copilot安装和使用体验测评

简介&#xff1a; OS Copilot是阿里云基于大模型构建的Linux系统智能助手&#xff0c;支持自然语言问答、命令执行和系统运维调优。本文介绍其产品优势、功能及使用方法&#xff0c;并分享个人开发者在云服务器资源管理中的实际应用体验。通过-t/-f/管道功能&#xff0c;OS Cop…

Python Flask框架学习汇编

1、入门级&#xff1a; 《Python Flask Web 框架入门》 这篇博文条理清晰&#xff0c;由简入繁&#xff0c;案例丰富&#xff0c;分十五节详细讲解了Flask框架&#xff0c;强烈推荐&#xff01; 《python的简单web框架flask【附例子】》 讲解的特别清楚&#xff0c;每一步都…