跳转到页面内容
圆点软件.YUANDIAN SOFTWARE

YUANDIAN / INSIGHTS & IDEAS

缓存穿透、击穿与雪崩的区分处理方式

穿透、击穿、雪崩看着相似,成因和处理方式完全不同。分清是哪一种,才能选对空值占位、互斥重建或过期打散这些手段。

专注软件开发 · 连接业务与可能技术分享
缓存穿透、击穿与雪崩的区分处理方式

三个问题对应三种成因

穿透是查询根本不存在的数据,缓存永远不命中,请求全部落到数据库。常见于被构造的非法标识,或者参数解析后出现偏差。

击穿是某个热点键恰好过期,瞬间大量请求同时回源。区别于穿透的地方在于数据是存在的,只是那一刻缓存里没有。

雪崩是大批键在同一时间集中失效,或者缓存服务整体不可用,导致数据库压力骤增。三者的处理手段有重叠,但切入点不同。

穿透的拦截思路

对查询结果为空的键也写一份短过期时间的空值占位,避免同样的非法参数反复打到数据库。过期时间不宜太长,防止数据后来真实存在了却一直读到空。

在入口做参数校验,格式不合法或超出范围的直接返回,不要进入缓存与数据库链路。这是成本最低的一层。对空值占位的键要单独统计数量,异常增长就说明有人在扫描不存在的标识。缓存键的命名要能按业务前缀批量失效,避免只能全量清空。

数据量可控且需要频繁判断存在性的场景,用位图过滤器先挡一轮。它有误判为存在的可能,所以只能作为前置过滤,不能作为最终判定。

击穿的应对

热点数据的过期时间可以设得长一些,并配合后台任务主动刷新,让缓存始终有值。牺牲一点实时性换取数据库的稳定。

对同一个键的回源加互斥锁,只有一个请求去查库并回填,其余请求短暂等待后重试读取。锁要有超时,避免持有者异常导致阻塞。

逻辑过期是另一种思路:值里带一个逻辑过期时间,物理上不过期,发现逻辑过期后由一个线程异步重建,其他请求先返回旧值。

雪崩的预防

过期时间加随机扰动是最简单的做法,把集中失效摊开到一个区间内。基础时长加上一个随机偏移即可。

缓存层做多级或者高可用部署,避免单点故障导致整体不可用。客户端要配好超时与重试,并且限制重试次数,防止故障时重试风暴把后端压垮。

关键链路要有降级方案。缓存不可用时返回兜底数据或者直接拒绝部分非核心请求,保住核心业务。降级的开关要能随时手动调整。

一致性与运行监控

更新数据时先更新数据库再删除缓存,是更常用的顺序。删除比更新缓存更安全,能避免并发写导致的中间态。删除失败要有重试队列或者依赖过期时间兜底。

缓存里的值可以带上版本或更新时间,读出来时判断是否已陈旧,便于做后续的校验和补偿。

命中率、回源数量、响应时间、连接数是最该盯的几个指标。命中率突然下降通常意味着有异常键或者数据被批量清理。给回源请求量设阈值告警,出现陡增就说明缓存层出了问题。

缓存容量要留有余量,接近内存上限时淘汰会变得频繁,命中率随之下降,形成恶性循环。

Redis缓存

LET’S BUILD TOGETHER

让思考,成为下一步行动。

把业务场景与初步想法告诉我们,一起找到合适的实现方式。