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

在百亿流量面前,让“不存在”无处遁形——Redis 缓存穿透的极限攻防实录

一、开场白:凌晨 01:47 的“幽灵峰值”
2024 年 3 月 18 日,某头部内容平台的监控大屏突然飘红:网关 502 比例从 0.01% 蹿至 17%,Redis 集群命中率仍保持 99.3%,数据库 CPU 却逼近 95%。值班同学第一反应是“有热点 key 过期”,但查看 Keyspace 后发现过期事件寥寥。十分钟后,根源浮出水面:攻击者利用“内容 ID 自增 + 随机偏移”的方式,瞬时灌入 2300 万个根本不存在的 ID,导致缓存穿透。本文以这次真实事件为蓝本,拆解百亿流量场景下穿透攻防的极限实践。

二、业务画像:内容 ID 的结构化特征
平台内容 ID 为 64 位 long,高 24 位是业务线,中 24 位是时间戳(天级),低 16 位是随机序列。合法 ID 总量约 120 亿,但每日新增仅 8000 万。攻击者只需在时间戳区间外随机生成,即可 100% 命中“不存在”。该特征决定了传统布隆过滤器难以覆盖全部 key 空间,必须引入“时间窗口 + 分片”策略。

三、第一道闸:网关层的“零成本”拦截

  1. 正则黑名单
    在 Nginx 层加入 Lua 脚本,校验 ID 时间戳是否在未来 1 天或早于 90 天前,直接返回 400。该规则零内存占用,拦截 80% 的伪造流量。

  2. Token Bucket 限速
    对“空结果”响应单独建桶,阈值设为正常用户均值的 5 倍,超过即滑块验证码。

  3. 负反馈标记
    连续触发 3 次空结果的用户 Cookie 打标,后续 10 分钟所有请求降级到“只读缓存”,禁止回源数据库。

四、第二道闸:Redis 侧的“分片布隆”

  1. 空间模型
    120 亿 key 若用单层布隆,需要 14.4 Gb 内存,远超单机预算。采用“业务线分片 + 时间滚动”方案:

    • 每个业务线独享一个 64 Mb 的 Bloom Filter;

    • 以“天”为单位滚动,过期 90 天的 filter 直接丢弃;

    • 总内存占用 = 业务线数量 × 64 Mb ≈ 1.1 Gb。

  2. 并发写入
    内容发布时同步写 MySQL 与布隆过滤器,写过滤器使用 Redis 的 BF.ADD,失败时通过 MQ 补偿,保证最终一致。

  3. 假阳性治理
    假阳性概率 p=0.01%,每日误判 12 万请求。引入“二次确认”策略:过滤器返回存在时,先查 Redis,miss 后再查 MySQL;过滤器返回不存在时,直接返回 404。这样只有 12 万请求多一次 Redis 查询,成本可接受。

五、第三道闸:空值缓存的“动态 TTL”

  1. 分层 TTL
    将空值缓存划分为 L1(Redis,30 秒)、L2(Caffeine 本地,5 秒)。L1 miss 后回源 DB,DB 返回空则写 L1 并携带 TTL=30 秒;L2 用于抗突发热点。

  2. TTL 自适应
    引入 PID 控制器:

    • 输入:过去 1 分钟空结果 QPS 与数据库 CPU;

    • 输出:TTL 在 5~300 秒之间动态调整;

    • 目标:CPU 保持在 60% 以下,Nil Ratio 低于 2%。
      实践表明,自适应后穿透峰值降低 92%,平均 TTL 收敛在 45 秒。

六、第四道闸:数据库侧的“最后一击”

  1. 空结果表
    创建表 fake_id_log(id bigint primary key, gmt_create datetime),空结果写入该表,替代直接回主库。

  2. 合并写
    使用 MySQL 的 INSERT IGNORE 批量 1000 条,减少行锁冲突。

  3. 异步回填
    消费者发现空结果 ID 存在于正式表时,删除空结果记录并刷新缓存,闭环纠错。

七、演练与度量:如何证明防御有效

  1. 红蓝对抗
    每月随机挑选 2 台云主机模拟攻击,工具可配置 QPS、ID 区间、随机度。对抗后输出三项指标:

    • 拦截率 = 1 - 到达数据库的请求 / 总攻击请求;

    • 误杀率 = 正常请求被 404 的比例;

    • 恢复时长 = 从攻击结束到系统指标恢复常态的用时。

  2. 影子过滤器
    生产环境并行运行一套“影子布隆”,参数与正式完全一致,但只记录日志不拦截。对比两者指标,可量化假阳性漂移。

  3. 混沌工程
    利用 ChaosBlade 随机下线 30% Bloom 节点,验证剩余节点能否承担流量;同时观测 TTL 自适应算法的收敛速度。

八、踩坑日记:三次血与泪的教训

  1. Lua 正则回溯
    早期使用 ngx.re.match 贪婪模式,遇到 128 位超长 ID 时 CPU 爆涨,改为 ngx.re.find 非回溯后解决。

  2. 过滤器重建抖动
    某次全量重建布隆时,采用 BF.LOADCHUNK,因网络抖动导致 3 秒阻塞,引发雪崩。后改为“滚动双缓冲”:新过滤器在后台构建,构建完成后原子替换。

  3. PID 控制器震荡
    初期 PID 参数激进,TTL 在 5 秒和 300 秒之间来回跳,造成缓存颠簸。引入一阶滞后滤波后,曲线平滑。

九、尾声:穿透的尽头是成本博弈
在 120 亿 key 面前,100% 拦截是不经济的。最终目标是把穿透概率压到“可忽略”区间,同时保证内存、CPU、人力成本线性可控。经过 6 个月迭代,平台 Nil Ratio 稳定在 0.7%,误杀率 0.05%,单条请求新增 RT 0.8 ms,全年节省数据库费用 120 万元。幽灵仍在,但已被关进笼子。


文章转载自:
http://acyloin.wjrtg.cn
http://beechy.wjrtg.cn
http://biotherapy.wjrtg.cn
http://assertorily.wjrtg.cn
http://agrypnotic.wjrtg.cn
http://catchall.wjrtg.cn
http://abomasum.wjrtg.cn
http://argentite.wjrtg.cn
http://accrescent.wjrtg.cn
http://bonesetter.wjrtg.cn
http://bodkin.wjrtg.cn
http://acetabularia.wjrtg.cn
http://celadon.wjrtg.cn
http://absorptive.wjrtg.cn
http://asme.wjrtg.cn
http://bibliopoly.wjrtg.cn
http://chlorophyll.wjrtg.cn
http://carborane.wjrtg.cn
http://caldoverde.wjrtg.cn
http://aubergine.wjrtg.cn
http://blotting.wjrtg.cn
http://albumin.wjrtg.cn
http://arrowworm.wjrtg.cn
http://amalgam.wjrtg.cn
http://attritus.wjrtg.cn
http://burstproof.wjrtg.cn
http://backspace.wjrtg.cn
http://brazil.wjrtg.cn
http://bladesmith.wjrtg.cn
http://animadversion.wjrtg.cn
http://www.dtcms.com/a/280587.html

相关文章:

  • uniapp 微信小程序Vue3项目使用内置组件movable-area封装悬浮可拖拽按钮(拖拽结束时自动吸附到最近的屏幕边缘)
  • 解锁Python爬虫:数据获取与清洗的进阶指南
  • 运维技术教程之Jenkins的秘钥设置
  • TP商城登录系统测试报告
  • Python Fabric库详解:从入门到自动化运维实战
  • C++ Boost Aiso TCP 网络聊天(服务端客户端一体化)
  • 【论文阅读 | PR 2024 |ITFuse:一种用于红外与可见光图像融合的交互式 Transformer】
  • 第三章 OB SQL 引擎高级技术
  • 【网络安全】大型语言模型(LLMs)及其应用的红队演练指南
  • 【Git】详解git commit --amend用法以及使用遇到的问题
  • Vue 2 和 Vue 3 中,组件的封装、二次开发和优化
  • Sersync和Rsync部署
  • Keil 5下载的时候提示“No J-Link found”
  • 《恋与深空》中龙和蛇分别是谁的代表
  • 25、企业能源管理(Energy):锚定双碳目标,从分类管控到智能优化的数字化转型之路
  • flutter弹窗:fluttertoast
  • HTTP 性能优化实战:突破高并发瓶颈的工业级方案
  • elasticsearch 下载/安装
  • 飞睿UWB超宽带定位测距技术,数字钥匙重塑智能生活,高精度厘米级定位无感解锁
  • ffmpeg音视频处理大纲
  • HR数字化转型:3大痛点解决方案与效率突破指南
  • QT 中各种坑
  • 基于Scikit-learn的机器学习建模与SHAP解释分析
  • 如何解决 Spring Boot 使用 Maven 打包后运行失败的问题(附详细排查步骤)
  • [雨云教程]端口冲突该如何解决
  • 前端报错:“Uncaught SyntaxError: missing ) after argument list
  • 【学习笔记】条件变量+互斥锁解决问题
  • 快速排序:原理、示例与 C 语言实现详解
  • 区块链的三种共识机制——PoW、PoS和DPoS原理
  • [面试] js 数组面试题