给 API 加一层缓存:从穿透、击穿到雪崩的工程实践
很多接口变慢,并不是数据库不够快,而是每次请求都在重复计算相同的结果。商品详情、排行榜、配置信息这类读多写少的数据,完全可以放进缓存,让请求不再打到数据库。缓存看起来简单,真正上线后才会发现,它自己也会带来新问题:穿透、击穿和雪崩。
一、缓存放在哪里
最常见的做法是在应用和数据库之间加一层分布式缓存:请求先查缓存,命中直接返回,未命中再查数据库并回填。回填时要设置过期时间,更新频繁的数据给几分钟,几乎不变的配置可以给几小时。过期时间要按数据变化频率来定,不能图省事统一写一个值。
二、缓存穿透:查不到的东西被反复查
如果请求的参数根本不存在,比如一个不存在的商品编号,缓存和数据库里都没有,每次请求都会穿透到数据库。随机编号轮询会很快拖垮数据库。解法有两个:一是把空结果也缓存起来,过期时间设短一点;二是在缓存前加布隆过滤器,先判断编号是否存在。两者可以一起用,布隆过滤器拦截大部分无效请求,空值缓存兜底。
三、缓存击穿:热点 Key 在同一时刻过期
热点 Key 过期的一瞬间,大量并发请求同时发现缓存为空,一起涌向数据库,这就是击穿。解法是不要让所有请求都去重建缓存:用互斥锁只放一个请求去查库重建,其余请求等待或返回旧值;或者给数据加逻辑过期时间,缓存本身不过期,由后台线程异步刷新。对读多写少的热点数据,逻辑过期更稳妥。
四、缓存雪崩:大量 Key 在同一时间失效
如果大量 Key 用了相同过期时间,又在同一时刻失效,数据库会瞬间承受全部流量;缓存服务本身宕机时也会发生同样的事。预防有三点:过期时间加上随机值,把失效时间打散;做多级缓存,本地缓存挡住一部分请求;给数据库加限流和熔断,宁可部分请求降级,也不要把数据库打挂。
五、缓存不是银弹
缓存能缓解读压力,也带来了不一致和运维成本。写频繁的数据不适合缓存,强一致的场景不能只靠缓存。上线后要盯三个指标:命中率、平均响应时间和回源请求量。命中率骤降往往是穿透或雪崩的前兆,回源量突增可能是热点 Key 过期了。把这些指标接进监控告警,缓存才能真正成为加速器,而不是新的故障源。
缓存的正确用法可以概括成三句话:先判断数据是否适合缓存,再给失效留好退路,最后用监控守住底线。这样加的缓存,才是帮系统提速的缓存。
- 点赞
- 收藏
- 关注作者
评论(0)