事故复盘:一次缓存穿透,把数据库打到了 100%
【摘要】 事故现象: 晚上八点,商品详情接口 P99 从 80ms 涨到 4 秒,数据库 CPU 打满。排查发现大量请求查询一个刚下架的商品 ID,缓存里没有,每次都打到数据库,数据库返回空,也没有回写缓存。请求量本身不大,但每个请求都穿透到 DB,叠加起来把连接池占满。原因拆解: 缓存只缓存了“存在的商品”,不存在的商品不缓存。攻击者或爬虫随便构造 ID,就能绕过缓存。这是典型的缓存穿透。修复措施:...
事故现象: 晚上八点,商品详情接口 P99 从 80ms 涨到 4 秒,数据库 CPU 打满。排查发现大量请求查询一个刚下架的商品 ID,缓存里没有,每次都打到数据库,数据库返回空,也没有回写缓存。请求量本身不大,但每个请求都穿透到 DB,叠加起来把连接池占满。
原因拆解: 缓存只缓存了“存在的商品”,不存在的商品不缓存。攻击者或爬虫随便构造 ID,就能绕过缓存。这是典型的缓存穿透。
修复措施: 第一,对查询结果为空的 key 也缓存一个短 TTL 的空值标记,比如 60 秒。第二,对明显非法的 ID 格式在入口层直接拒绝。第三,热点 key 加互斥锁,避免缓存失效瞬间大量请求同时回源。第四,数据库连接池设等待超时,快速失败而不是无限排队。
更根本的反思: 缓存设计不能只考虑“命中率”,还要考虑“未命中的代价”。穿透、击穿、雪崩是三种不同的失效模式:穿透是查不存在的数据,击穿是热点 key 过期,雪崩是大量 key 同时过期。对应的手段不同,空值缓存、互斥锁、过期时间加随机抖动,别混为一谈。
这次事故的教训不是“加个空值缓存就完了”,而是缓存层要有“防御性设计”。假设流量里一定有异常请求,缓存要能挡住它们,而不是把压力原样传给数据库。
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)