4. 缓存一致性理论基础:缓存穿透、缓存击穿、缓存雪崩、数据一致性模型
在构建高并发、高可用的分布式系统时,缓存是提升性能的核心手段。然而,缓存引入后也带来了三个经典的高危场景——缓存穿透、缓存击穿、缓存雪崩,以及一个架构层面的核心难题——数据一致性。本章将深入剖析这些问题的成因、危害与治理策略,为后续的 OpenAPI 契约设计奠定理论基础。
4.1 缓存穿透
定义:查询一个一定不存在的数据,由于缓存中不命中,请求直接穿透到数据库,导致数据库压力骤增。
典型场景:恶意攻击者伪造大量不存在的用户 ID(如负数、超长 ID)发起查询,缓存层永远无法命中,所有请求直达数据库。
核心危害:数据库连接池被耗尽,导致正常请求也无法响应,引发级联故障。
4.1.1 治理策略
| 策略 | 原理 | 适用场景 | 注意事项 |
|---|---|---|---|
| 缓存空对象 | 将查询结果为 null 的 key 也缓存起来,设置较短的 TTL(如 30s) | 数据量不大,空 key 数量可控 | 需要防止大量空 key 占用内存;注意 TTL 过期后仍可能穿透 |
| 布隆过滤器 | 在缓存层之前加一层 Bloom Filter,判断 key 是否存在 | 数据量大,空 key 比例高 | 存在一定误判率;需要定期重建过滤器 |
| 参数校验 | 在 API 网关层对请求参数进行合法性校验 | 所有场景 | 只能拦截明显不合法的参数,无法应对合法 ID 但数据不存在的情况 |
4.2 缓存击穿
定义:一个热点 key 在缓存失效的瞬间,大量并发请求同时涌入,直接打到数据库。
典型场景:秒杀商品详情页、微博热搜榜。某个 key 的访问量极大,一旦缓存过期,所有请求同时回源。
与缓存穿透的区别:缓存击穿针对的是存在的热点数据,只是缓存恰好过期;缓存穿透针对的是不存在的数据。
4.2.1 治理策略
- 互斥锁(Mutex Lock):当缓存失效时,只允许一个线程去数据库加载数据,其他线程等待。适用于并发量极高但数据库压力敏感的场景。
- 逻辑过期:在缓存数据中额外存储一个逻辑过期时间字段,由业务代码判断是否过期。过期时异步更新缓存,避免阻塞读请求。
- 热点 key 永不过期:对确定的热点 key 不设置 TTL,通过后台任务定期刷新。适用于数据变化不频繁的场景。
4.3 缓存雪崩
定义:大量 key 同时失效,或者缓存节点宕机,导致海量请求直接压垮数据库。
典型场景:缓存服务重启、大量 key 设置了相同的过期时间(如凌晨 0 点统一过期)。
4.3.1 治理策略
| 维度 | 策略 | 说明 |
|---|---|---|
| 缓存失效 | 过期时间加随机值 | 在基础 TTL 上增加 ±10%~30% 的随机偏移,避免集中失效 |
| 多级缓存 | 本地缓存(Caffeine) + 分布式缓存(Redis)组合,本地缓存扛住第一波流量 | |
| 缓存节点 | Redis 哨兵/集群 | 主从切换 + 分片,避免单点故障 |
| 限流降级 | 在数据库层前置限流组件(如 Sentinel),超出阈值直接返回降级数据 |
4.4 数据一致性模型
缓存与数据库之间必然存在数据同步延迟,这引出了数据一致性的核心问题。根据业务对一致性的容忍度,主要分为两种模型:强一致性 和 最终一致性。
4.4.1 强一致性
定义:数据更新后,任何后续的读操作都能立即读取到最新的值。系统保证所有节点在同一时刻看到的数据完全相同。
- 实现方式:分布式事务(2PC/3PC)、Paxos/Raft 共识算法、同步复制。
- 优点:业务逻辑简单,数据无歧义。
- 缺点:性能开销大,可用性降低(CAP 理论中的 CP 模型)。
- 适用场景:金融交易、库存扣减、订单状态。
4.4.2 最终一致性
定义:数据更新后,不保证立即一致,但经过一段时间后,所有副本最终会达到一致状态。
- 实现方式:异步复制、消息队列、补偿机制(如 TCC)、CRDT(无冲突数据类型)。
- 优点:高可用、高性能、可扩展性强。
- 缺点:存在短暂的不一致窗口,业务需要容忍。
- 适用场景:用户资料、文章阅读量、社交动态。
架构决策建议:在缓存治理中,绝大多数场景选择最终一致性。强一致性通常只在核心资金链路中使用,且需要配合分布式锁或事务消息。
4.4.3 缓存一致性常见模式
| 模式 | 操作顺序 | 一致性等级 | 风险 |
|---|---|---|---|
| Cache Aside | 读:先读缓存,miss 则读 DB 并回写缓存 写:先更新 DB,再删除缓存 |
最终一致性 | 删除缓存失败导致脏数据 |
| Read/Write Through | 缓存层代理所有读写操作,缓存与 DB 同步更新 | 强一致性(同步模式) | 缓存层成为瓶颈 |
| Write Behind | 先更新缓存,异步批量写入 DB | 最终一致性 | 缓存宕机导致数据丢失 |
4.5 本章小结
- 缓存穿透:核心在于拦截不存在的数据,布隆过滤器 + 缓存空对象是标准解法。
- 缓存击穿:核心在于保护热点 key,互斥锁和逻辑过期是主流方案。
- 缓存雪崩:核心在于避免大规模同时失效,过期时间加随机值 + 多级缓存是基础防线。
- 数据一致性:强一致性适用于资金类场景,最终一致性适用于大多数业务场景。缓存治理中优先选择最终一致性,配合补偿机制保证数据可靠。