基于本文回答

播面 播面

文图音视,全方位拆解八股文
0
评论

黑客恶意伪造大量不存在的商品ID请求我们的接口,如何利用Redis防御“缓存穿透”?

知识点图片

黑客恶意伪造大量不存在的商品ID请求接口,导致请求直接绕过缓存(Redis)打到数据库(MySQL),这种现象在架构上称为“缓存穿透”(Cache Penetration)。如果并发量大,极易导致数据库瘫痪。

针对这种恶意攻击,利用 Redis 防御主要有两种核心方案,以及配合业务层的综合防御策略


核心方案一:布隆过滤器(Bloom Filter)—— 终极防线(最推荐)

当黑客使用不断变化且随机的假ID进行攻击时,布隆过滤器是最佳选择。

1. 原理:
布隆过滤器是一种空间效率极高的概率型数据结构。它的特点是:

  • 判断不存在:100%准确。 如果布隆过滤器说商品ID不存在,那它一定不存在。
  • 判断存在:存在极小的误判率(False Positive)。 如果它说存在,可能存在也可能不存在(但这个概率可以控制在极小,比如0.01%)。

2. 应对流程:

  1. 预热: 系统启动时,将数据库中所有真实存在的商品ID的哈希值存入 Redis 的布隆过滤器中。
  2. 拦截: 当请求到达时,先用 Redis 布隆过滤器判断该ID是否存在。
  3. 处理:
    • 如果布隆过滤器判定不存在,直接按非法请求返回(例如抛出参数错误或404),请求根本不会触及缓存和数据库
    • 如果布隆过滤器判定存在,再继续执行常规流程(查Redis -> 查MySQL)。即使有0.01%的假ID漏网,数据库也完全扛得住。

3. Redis 实现方式:

  • RedisBloom 模块: 如果你的 Redis 安装了该模块,可以直接使用 BF.ADDBF.EXISTS 命令。
  • Redisson 客户端(Java): 实际开发中最常用,Redisson 封装了完整的分布式布隆过滤器。
    java
    // 1. 初始化布隆过滤器,预计元素1亿,误差率0.01%
    RBloomFilter<Long> bloomFilter = redisson.getBloomFilter("product_id_bloom");
    bloomFilter.tryInit(100000000L, 0.0001);
    
    // 2. 请求到来时的判断
    if (!bloomFilter.contains(productId)) {
        return "非法商品ID,请求被拒绝"; // 直接拦截
    }
    // 3. 继续查缓存查DB...

核心方案二:缓存空对象(Cache Null Value)—— 简单快速的补救

如果黑客是用少量固定的几个假ID进行高频攻击,或者你暂时无法引入布隆过滤器,可以使用这个方案。

1. 原理:
当一个ID在 Redis 中查不到,去数据库中也查不到(返回 null)时,不要什么都不做。相反,将这个“空结果”也缓存到 Redis 中(例如存一个特殊的标识符 "NULL")。

2. 应对流程:

  1. 请求商品 id=999999,Redis 未命中。
  2. 查询 MySQL,发现 id=999999 不存在。
  3. 将键值对 product:999999 : "NULL" 写入 Redis,并设置一个较短的过期时间(TTL)。
  4. 下一次黑客再请求 id=999999 时,Redis 会直接命中并返回空,保护了数据库。

3. 注意事项与防备:

  • 必须设置短期过期时间(如 30秒 - 5分钟): 防止该ID日后真的被添加进数据库而导致数据不一致,同时也防止占用过多内存。
  • 内存暴涨风险: 如果黑客每次都用完全不同的新ID,Redis 会缓存海量的“空对象”,导致内存耗尽(OOM)。此时必须配合内存淘汰策略(如 allkeys-lru),并且说明此方案不如布隆过滤器适合防御“动态随机ID”的攻击。

综合防御:不能仅靠 Redis,需构建立体防线

面对恶意攻击,缓存层只是最后一道防线,真正的防御应该尽可能前置:

1. 接口层的参数校验(基本功)

黑客伪造的ID往往不符合业务规则。

  • 长度/格式校验: 如果你的商品ID是 18 位雪花算法生成的纯数字,直接在网关或 Controller 层把 10位数的、带字母的请求拦截掉。
  • 校验位/签名: 如果可以,在ID中加入校验位(类似身份证最后一位),或者要求请求带上加密签名(Token/Sign),验签失败直接拒绝。

2. 利用 Redis 进行 IP 频次限流(防刷)

针对异常请求的源头进行打击。

  • 如果同一个 IP 或同一个 UserID 在短时间内发起大量请求,尤其是大量请求不存在的商品,利用 Redis 的 ZSET 或令牌桶算法进行限流。
  • 一旦超过阈值,将该 IP 写入 Redis 的“黑名单”(设置过期时间如冻结2小时),在网关层直接拦截。

3. WAF / 恶意风控系统

接入专业的 Web 应用防火墙(WAF)或风控系统,通过分析访问行为(如无浏览器指纹、无页面停留时间、纯接口强刷)来识别爬虫和黑客,在流量入口处直接阻断。

总结建议

针对“黑客恶意伪造大量不存在ID”的具体场景,最优解是:
基础参数校验拦截 + Redis 布隆过滤器(过滤掉99.99%的随机假ID) + 缓存空对象(应对极小概率穿透布隆过滤器的漏网之鱼) + Redis IP 限流封禁。

00:00
00:00