ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

缓存穿透雪崩击穿,后端必会的三种解决方案

缓存穿透雪崩击穿,后端必会的三种解决方案 缓存是后端性能的基石用得好能抗住百万流量用不好则会让数据库瞬间崩溃。在面试和实际生产中缓存穿透、缓存雪崩、缓存击穿是绕不开的三座大山。它们看似相似实则成因和应对策略截然不同。掌握这三种问题的解决方案是每个后端工程师的必修课。一、缓存穿透查询不存在的数据缓存穿透是指客户端请求的数据在缓存和数据库中都不存在。由于缓存不命中每次请求都会落到数据库上。如果有人恶意用不存在的ID频繁攻击数据库压力会急剧上升。解决方案1. 布隆过滤器拦截。在缓存层之前加一个布隆过滤器将所有可能存在的key哈希到 bitmap 中。请求进来先查布隆过滤器如果判断不存在直接返回空不再访问缓存和数据库。布隆过滤器有极小的误判率但不会漏判适合拦截海量无效请求。2. 缓存空值。对于查询结果为空的key仍然将其缓存起来值设为空对象或特殊标记并设置较短的过期时间如30秒到5分钟。这样后续相同请求会直接命中缓存避免打到数据库。缺点是会占用少量缓存空间且可能造成短期的数据不一致。3. 接口层参数校验。在Controller层对请求参数做合法性校验比如ID必须为正整数、长度符合规则等把明显非法的请求直接拦截在业务逻辑之外。这是成本最低的第一道防线。二、缓存雪崩大量缓存同时失效缓存雪崩是指在同一时间大量缓存key同时过期或者缓存服务整体宕机导致所有请求瞬间涌向数据库像雪崩一样压垮后端。解决方案1. 过期时间加随机值。这是最常用的手段。在设置缓存过期时间时在基础时间上增加一个随机偏移量比如原本统一30分钟改为30分钟±5分钟。这样不同key的失效时间被分散开不会在同一秒集体失效。2. 保证缓存高可用。使用Redis哨兵模式或集群模式避免单点故障。即使主节点宕机从节点能迅速接管。同时可以引入多级缓存本地缓存如Caffeine作为第一层Redis作为第二层即使Redis整体不可用本地缓存仍能扛住部分流量。3. 服务降级与熔断。使用Sentinel或Hystrix对数据库访问做限流和熔断。当检测到数据库压力过大时自动降级返回兜底数据或友好提示保护数据库不被压垮。事后通过日志和监控快速恢复缓存。三、缓存击穿热点key突然失效缓存击穿与雪崩不同它针对的是某个被高频访问的热点key。当这个key过期的一瞬间大量并发请求同时发现缓存失效于是全部去数据库加载数据导致数据库瞬时压力飙升。解决方案1. 互斥锁。当缓存失效时只允许一个线程去数据库加载数据其他线程等待。加载完成后将数据写入缓存再释放锁。其他线程重新从缓存读取。可以用Redis的SETNX实现分布式锁注意设置锁的超时时间防止死锁。2. 逻辑过期。不设置物理过期时间而是在value中额外存储一个逻辑过期字段。当发现逻辑过期时异步启动一个线程去更新缓存当前请求仍然返回旧数据。这样所有请求都不会阻塞也不会打到数据库只是短时间内数据可能不是最新的。3. 热点key永不过期。对于极少数访问量极高的key可以设置为永不过期通过后台定时任务或消息队列触发更新。这样彻底避免了失效瞬间的击穿问题但需要保证更新机制可靠。总结缓存穿透、雪崩、击穿三者的核心区别在于穿透是查不存在的数据雪崩是大面积失效击穿是单个热点失效。对应的解决思路也各有侧重穿透靠拦截和空值缓存雪崩靠错峰失效和高可用击穿靠加锁和异步更新。在实际生产中这些方案往往组合使用。比如用布隆过滤器防穿透用随机过期时间防雪崩用互斥锁防击穿。同时配合完善的监控告警才能让缓存真正成为系统的护城河而不是压垮数据库的最后一根稻草。
返回列表