缓存穿透问题与解决方案

缓存穿透问题详解

缓存穿透 是指查询一个根本不存在的数据。由于缓存(Redis)和数据库(MySQL)中都没有该记录,每次针对此数据的请求都会由于缓存未命中(Miss)而直接"穿透"到后端数据库。

如果在短时间内有大量此类恶意攻击或异常请求,数据库将承受巨大的瞬时压力,可能导致系统崩溃。


1. 核心流程与成因

正常情况下,缓存作为数据库的屏障拦截了大部分请求。但在缓存穿透场景下:

  1. 请求到达 :用户查询一个 ID 为 -1 或随机生成的非法数据。
  2. 缓存失效:Redis 中没有该 ID 的记录。
  3. 透传数据库:请求直接查询数据库,结果依然为空。
  4. 循环往复:由于数据库结果为空,通常代码不会将此空结果写入缓存,导致下一次相同请求依然会穿透。

2. 解决方案

为了防止数据库被"穿透",业界主要采用以下两种成熟方案:

方案一:缓存空对象(Cache Null Object)

这是最简单、最常用的方案。当数据库返回空结果时,依然将一个特殊的"空标记"或 null 写入缓存,并设置一个较短的过期时间。

  • 优点:实现简单,维护成本低。
  • 缺点 :
    • 消耗额外的内存空间(缓存了大量无意义的空键)。
    • 可能导致短期的不一致(如果此时数据库刚好插入了该数据,缓存中可能依然存着空对象)。
java 复制代码
public Object queryData(String key) {
    // 1. 查缓存
    Object val = redis.get(key);
    if (val != null) return val;

    // 2. 查数据库
    Object dbVal = mapper.select(key);
    if (dbVal == null) {
        // 核心:即使为空也存入缓存,设置 2 分钟过期时间
        redis.setex(key, 2, TimeUnit.MINUTES, ""); 
        return null;
    }
    
    redis.set(key, dbVal);
    return dbVal;
}
方案二:布隆过滤器(Bloom Filter)

在进入缓存层之前,先通过布隆过滤器拦截非法请求。布隆过滤器是一种紧凑的概率性数据结构,用于快速判断一个元素是否在一个集合中。

  • 核心逻辑:

    • 如果布隆过滤器判断不存在 ,那么该数据一定不存在,直接拦截。
    • 如果判断存在 ,数据可能存在(存在极小的误判率),允许通过去查缓存。
  • 优点:内存占用极低,不需要存储具体的 Key。

  • 缺点:

    • 代码复杂度高,需要预热加载所有合法的 Key。
    • 无法物理删除(数据从库中删除后,布隆过滤器难以实时同步移除)。
相关推荐
旋生万物44 分钟前
Redis 缓存雪崩?不是 TTL 一样,是过期相位同步塌陷(附打散脚本)
redis·缓存·aigc·螺旋生成论·螺旋相位
大漠孤烟s9 小时前
7.mybatisplus学习-条件构造器、插件、通用枚举、多数据源环境、MybatisX
mybatis
ee又momo9 小时前
MyBatis-Plus 用了就回不去,这些功能真香
mybatis
全栈弄潮儿²⁰²⁴6 天前
AI Agent 开发实战(30):限流、缓存与成本控制
人工智能·gpt·缓存·agent·限流·agi·成本控制
Together_CZ7 天前
DeepSeek-V4.1-Flash:Pushing the Limits of KV Cache Compression——推动 KV 缓存压缩的极限
缓存·llm·compression·kv cache·deepseek·v4.1-flash·推动 kv 缓存压缩的极限
大漠孤烟s7 天前
4.Mybatis学习-动态sql、缓存、逆向工程
mybatis
Pioneer000017 天前
我用 Redis + 网关做多模型 API 路由:缓存命中率 95%+ 的工程实践
人工智能·redis·后端·缓存·性能优化·架构
hweiyu008 天前
Redis命令:MSETNX
redis·缓存
wdfk_prog8 天前
ROS教程08:从 TransportTCP::connect() 追到 TCPROS Connection Header、序列化与 Socket 数据传输
运维·缓存·docker·容器·ros
是Dream呀8 天前
Harness 工程:让 Agent 真正把任务做完
人工智能·分布式·缓存·agent