1. 缓存一致性概述
1.1 为什么需要缓存一致性
在现代高并发架构中,缓存(如 Redis)被广泛用于加速数据读取、减轻数据库负载。然而,缓存与数据库是两套独立的存储系统,当数据发生写操作时,两者之间的数据差异(即“不一致”)会直接导致业务逻辑错误、用户看到过期数据甚至脏数据。缓存一致性的核心目标就是:保证缓存中的数据与数据库中的数据在可接受的时间窗口内保持逻辑等价。
业务影响案例: 电商库存场景中,若缓存显示库存为 1 但数据库实际已为 0,会导致超卖;金融账户余额若缓存未及时更新,可能引发重复扣款或余额显示错误。缓存一致性不是可选项,而是数据正确性的底线。
缓存一致性的必要性体现在三个层面:
- 数据正确性:避免用户读到过期数据(stale data)或脏数据(dirty data)。
- 业务连续性:防止因数据不一致导致的订单、支付、库存等核心链路故障。
- 合规审计:在金融、医疗等强监管行业,数据一致性是合规审查的硬性要求。
1.2 缓存与数据库的不一致问题来源
不一致问题的根源在于:缓存和数据库的更新操作不是原子性的。任何一次写操作,无论先写缓存还是先写数据库,都可能因为时序、并发或故障导致两者数据分裂。以下是四种典型的不一致场景:
| 场景 | 操作顺序 | 不一致原因 | 典型后果 |
|---|---|---|---|
| 先更新数据库,后更新缓存 | DB 写成功 → Cache 写失败 | 缓存写入操作因网络超时、Redis 故障等原因失败 | 缓存保留旧值,后续读请求拿到过期数据 |
| 先更新缓存,后更新数据库 | Cache 写成功 → DB 写失败 | 数据库写入失败(如约束冲突、死锁) | 缓存为新值,数据库为旧值,数据永久不一致 |
| 并发读写交错 | 读请求在写请求执行过程中插入 | 线程 A 写 DB,线程 B 读 DB 并写缓存,时序交错 | 缓存被写入旧数据,覆盖后续正确更新 |
| 缓存淘汰或过期 | 缓存失效后,多个读请求同时回填 | 缓存击穿时,多个线程同时查询 DB 并写缓存 | 缓存中可能被写入旧数据或数据错乱 |
关键认知: 不存在绝对零延迟的缓存一致性方案。工程上追求的是“最终一致性”或“强一致性窗口可控”,而非理论上的瞬时一致。理解不一致的来源,是设计一致性策略的第一步。
1.3 CAP 理论在缓存中的体现
CAP 理论(Consistency, Availability, Partition Tolerance)是分布式系统的基石,缓存系统作为分布式组件,同样受 CAP 约束。在缓存一致性场景中,CAP 的取舍直接影响架构设计:
- C(一致性):缓存与数据库之间的数据是否实时相同。强一致性要求每次读缓存都能读到最新写入的数据。
- A(可用性):缓存服务是否始终可响应。即使数据库故障或网络分区,缓存仍应返回数据(即使可能是旧数据)。
- P(分区容错性):当缓存节点与数据库节点之间网络中断时,系统能否继续运行。分布式部署中 P 是必选项。
在缓存一致性实践中,P 是必须保证的,因此我们只能在 C 和 A 之间做权衡:
| CAP 组合 | 缓存策略 | 典型场景 | 代价 |
|---|---|---|---|
| CP(放弃可用性) | 缓存写入失败时拒绝读请求,或强制从 DB 读取 | 金融交易、库存扣减 | 缓存故障时服务降级或不可用 |
| AP(放弃强一致性) | 允许缓存返回旧数据,后台异步同步 | 新闻列表、商品详情 | 用户可能看到短暂过期数据 |
| CA(放弃分区容错) | 缓存与数据库部署在同一节点,无网络分区 | 单体应用、本地缓存 | 无法水平扩展,单点故障风险 |
1.4 一致性模型分类
根据 CAP 取舍和业务容忍度,缓存一致性通常分为以下三种模型:
- 强一致性(Strong Consistency):每次读缓存都能读到最近一次写操作的结果。实现代价高,通常需要分布式锁或同步双写,且会降低可用性。
- 最终一致性(Eventual Consistency):允许短暂的不一致窗口,但保证在没有新写入的情况下,所有副本最终会达到一致状态。这是大多数互联网场景的首选。
- 因果一致性(Causal Consistency):有因果关系的操作按顺序可见,无因果关系的操作可以并发。介于强一致与最终一致之间。
实践建议: 对于绝大多数业务(如用户资料、商品信息),最终一致性配合合理的过期时间(TTL)和补偿机制即可满足需求。仅在资金、库存等核心链路中考虑引入强一致性方案(如 Redlock 分布式锁或数据库乐观锁)。
1.5 本章小结
缓存一致性是分布式缓存架构中最核心的挑战之一。本章明确了三个关键认知:
- 不一致的根源在于缓存与数据库更新操作的原子性缺失,以及并发读写时序的交错。
- CAP 理论决定了缓存系统必须在一致性(C)和可用性(A)之间做出取舍,而分区容错性(P)是分布式环境下的必选项。
- 一致性模型的选择应基于业务场景:核心链路倾向强一致,非核心链路采用最终一致+补偿机制。