F
Member
缓存能显著降低数据库压力,但设计不当时,缓存本身会成为故障放大器。三个名词容易混淆,成因和对策并不相同。
一、缓存穿透。 请求的数据在缓存和数据库中都不存在(如恶意构造的不存在的 ID),每次都会落到数据库。常用对策:对参数做合法性校验;对不存在的结果缓存空值并设置较短的过期时间;用布隆过滤器提前拦截一定不存在的键(注意布隆过滤器有误判率,且标准实现不便删除元素)。
二、缓存击穿。 某个热点 key 过期的瞬间,大量并发请求同时发现缓存未命中,一起去查数据库。常用对策:用互斥锁或“单飞”机制,只允许一个请求回源重建缓存,其余等待;或采用逻辑过期,先返回旧数据、后台异步刷新;对极热点数据可不设物理过期。
三、缓存雪崩。 大量 key 在同一时间集中过期,或缓存服务整体不可用,导致流量瞬间压向数据库。常用对策:给过期时间加随机抖动,避免集中失效;使用多级缓存;对数据库侧做限流、熔断和降级;缓存层用主从加哨兵或集群保证高可用。
四、共性建议。 缓存与数据库的一致性策略要事先明确(如先更新库再删缓存),并监控命中率、回源 QPS 与慢查询,演练缓存失效场景。
五、监控建议。 除了命中率之外,还应监控热点 key 的访问分布、回源数据库的并发数以及缓存重建耗时;上线前可以通过压测或故障演练,主动模拟缓存失效,验证限流和降级策略是否真正生效。
讨论问题:
1. 你们的系统里布隆过滤器是怎么落地的?如何处理数据新增?
2. 热点 key 的发现与保护,有没有成熟的做法?
3. 缓存与数据库的一致性,你们采用哪种方案,遇到过什么边界问题?
一、缓存穿透。 请求的数据在缓存和数据库中都不存在(如恶意构造的不存在的 ID),每次都会落到数据库。常用对策:对参数做合法性校验;对不存在的结果缓存空值并设置较短的过期时间;用布隆过滤器提前拦截一定不存在的键(注意布隆过滤器有误判率,且标准实现不便删除元素)。
二、缓存击穿。 某个热点 key 过期的瞬间,大量并发请求同时发现缓存未命中,一起去查数据库。常用对策:用互斥锁或“单飞”机制,只允许一个请求回源重建缓存,其余等待;或采用逻辑过期,先返回旧数据、后台异步刷新;对极热点数据可不设物理过期。
三、缓存雪崩。 大量 key 在同一时间集中过期,或缓存服务整体不可用,导致流量瞬间压向数据库。常用对策:给过期时间加随机抖动,避免集中失效;使用多级缓存;对数据库侧做限流、熔断和降级;缓存层用主从加哨兵或集群保证高可用。
四、共性建议。 缓存与数据库的一致性策略要事先明确(如先更新库再删缓存),并监控命中率、回源 QPS 与慢查询,演练缓存失效场景。
五、监控建议。 除了命中率之外,还应监控热点 key 的访问分布、回源数据库的并发数以及缓存重建耗时;上线前可以通过压测或故障演练,主动模拟缓存失效,验证限流和降级策略是否真正生效。
讨论问题:
1. 你们的系统里布隆过滤器是怎么落地的?如何处理数据新增?
2. 热点 key 的发现与保护,有没有成熟的做法?
3. 缓存与数据库的一致性,你们采用哪种方案,遇到过什么边界问题?