本文目录
缓存保护的核心,是数据库不会因缓存失效接收无限回源
穿透通常来自持续查询不存在的数据,击穿来自高热数据失效后并发回源,雪崩则可能来自大量键同时失效或整个缓存不可用。负缓存、请求校验、回源合并、过期时间分散与预热分别解决不同问题,但都需要回源并发与时间预算。缓存只适合有明确新鲜度边界的数据,余额、权限和库存不能依赖过期副本作最终判断。验收应包括空键、热键失效、内存淘汰和缓存故障,并验证数据库与用户结果。
按失效类型选择治理方法
| 失效类型 | 可优先验证的措施 | 必须处理的边界 |
|---|---|---|
| 不存在数据反复查询 | 输入校验、负缓存或存在性过滤减少无效回源 | 新数据写入后仍被负缓存误判,或过滤结构更新不及时 |
| 单个高热键失效 | 同一键回源合并、预热与有限等待 | 锁持有者失败导致阻塞,旧持有者删除新锁 |
| 大量键集中失效 | 过期时间分散、分批预热与回源预算 | 增加 TTL 却没有解决整体缓存故障 |
| 缓存服务不可用 | 按业务允许的旧值、降级或受控拒绝 | 所有实例直接绕过缓存,把数据库压垮 |
适用边界:先给每类缓存标注新鲜度
本文适用于数据库查询结果和可重建内容缓存。缓存并不自动满足业务一致性,资金、权限撤销和最终库存判断应有权威数据与受约束的写入规则,不能仅依赖读缓存命中。
商品说明可接受短暂旧值,账户权限可能不能接受撤销后的旧值;这些不是同一个缓存策略。给每类数据写明来源、更新事件、最大陈旧时间和故障时能否返回旧值。缓存键还必须包含租户、权限或版本维度,避免把不同用户可见范围错误地复用。
对于聚合统计和复合列表,应说明缓存版本是否覆盖全部组成数据。某个底层记录改变时,需要知道哪些聚合键会受影响;找不到失效关系就不应承诺强新鲜度。将缓存方案和业务读写路径一起评审,避免只有基础设施配置而缺少数据语义。
- 定义谁维护缓存、何时失效、谁提供最终事实。
- 把可降级展示与必须实时判断的操作分开。
穿透:无效请求要在昂贵查询前处理
反复访问不存在的业务标识,会使缓存每次未命中并查询数据库。先检查输入格式、权限与访问行为,再对可信的不存在结果建立短期负缓存,避免把外部故障当成“数据不存在”。
负缓存需要明确区别空结果与查询失败。新建数据后应能失效相关空值,过长的负缓存会让新数据迟迟不可见。布隆过滤等存在性结构可以减少查询,但要考虑误判、更新和重建;它不能替代权限判断,也不能作为最终不存在的永久证明。
- 将无效标识、无权限、真实空结果和依赖错误分别计数。
- 对负缓存容量与过期设置预算,避免随机键耗尽内存。
击穿:同一热键只让有限请求回源
热门数据失效时,多实例可能同时计算并查询。可按键合并并发回源,让少量请求负责重建,其余请求短时等待、返回允许的旧值或受控失败;等待必须有上限。
使用带过期的互斥机制时,应核对持有者标识并条件释放,防止旧持有者删除后来者的锁。锁过期并不说明旧工作已经停止,重建结果最好通过版本或更新时间避免覆盖更新值。这里的锁用于减少重复工作,不应成为余额或库存正确性的唯一保证。
- 为重建设置并发、耗时和失败退避预算。
- 检查持有者崩溃、超时、过期与并发更新时的最终缓存值。
雪崩:同时治理过期集中与服务失效
给 TTL 加分散量能缓解大批键同一时刻到期,但无法解决缓存节点故障、内存淘汰或网络超时。需要在应用侧限制总回源,并提前确定不同业务在缓存失效时如何工作。
Redis 的 maxmemory 与淘汰策略会影响哪些缓存丢失,淘汰、过期与读未命中应分开观察。缓存混放不能丢失的状态和可重建副本会使策略难以选择,应按用途评估隔离。不要把内存配满,只看命中率而忽略重建成本;一个小比例的昂贵未命中也可能压垮数据库。
- 分批预热热点,避免所有副本启动时集中重建。
- 演练缓存不可用后,数据库回源速率仍处于预算内。
实施步骤:按数据类别逐项上线保护
先梳理缓存清单与一致性要求,再区分失效症状;选择一条高价值读取路径,增加空值语义、回源合并与总量限制,随后设计更新失效、灰度发布和故障恢复,最后扩展到其他路径。
写入后何时失效缓存、并发旧读取是否会回填旧值,需要画时间线判断。延迟双删等技巧不能当作通用一致性证明,应针对并发窗口测试,必要时采用版本校验或明确的权威读取。缓存恢复后也要限制预热速度,避免已经受压的数据库再次被恢复动作击中。
- 保存键结构、容量、TTL、回源限制与更新策略。
- 灰度比较业务结果、数据库查询量与重建失败情况。
验收:主动制造四类未命中与更新竞争
验收不只检查命中率,而要确认错误输入、热键到期、大量淘汰和缓存中断不会让数据库失控。还需让数据更新与缓存回填交错执行,验证最终可见值符合业务新鲜度要求。
测试结束后检查数据库请求、应用排队与连接是否恢复,重建失败是否持续重试。对于允许旧值的路径,用户应能区分数据时间或处理中状态;必须实时判断的路径则验证正确拒绝与恢复。缓存带来的费用和运行复杂度也需列入收益评估。
不要在验收前删除全部缓存后立即把读压力推到生产数据库。受控测试应有隔离数据、停止条件和小范围故障注入,逐步验证回源上限。缓存恢复后继续观察新键写入与淘汰,如果频繁重建反复发生,应回到容量和访问分布分析,而不是无限加重试。
- 验证空值失效、条件释放、重建超时和陈旧值拒绝。
- 记录故障期间有效业务完成量、回源上限与恢复时间。
需求讨论中的问题
给所有键加随机 TTL 就能防止雪崩吗?
它主要分散集中到期,不能解决缓存服务不可用或内存淘汰。应用还需有回源预算、业务降级和受控预热,避免无限绕过缓存。
缓存命中率很高,为什么数据库仍然被打满?
应看未命中的绝对数量和单次回源成本。少量高成本查询、热键并发重建或无效标识穿透,可能在总体命中率很好时仍消耗大量数据库资源。
用 Redis 锁可以保证所有缓存一致性吗?
锁可以减少重复重建,但仍需处理过期、进程停顿、并发更新与故障切换。严格业务正确性应由权威存储与约束保障,缓存结果再通过版本或新鲜度规则校验。
缓存治理验收清单
可逐项勾选,辅助本次阅读;刷新页面后不保留。
参考资料
技术概念可进一步阅读以下资料;文中的业务场景与实施清单用于方案讨论。
- Redis:Key eviction
核验 maxmemory、淘汰策略以及命中、未命中、淘汰和过期统计含义。
- Redis:Distributed Locks with Redis
核验带持有者标识的条件释放与锁有效期边界;本文不将锁视为跨存储事务保证。
需要评估现有系统的性能瓶颈?
提供关键业务路径、真实峰值、服务器与数据库配置,以及现有压测或故障记录,月弦科技可据此梳理优化顺序、实施范围和可验证的验收条件。