4. 缓存一致性协议:Cache Aside、Read/Write Through、Write Behind Caching 原理与适用场景
在分布式缓存系统中,缓存与数据库之间的数据一致性是核心治理难题。不同的缓存一致性协议定义了应用程序如何与缓存及底层存储交互,直接影响系统的吞吐量、延迟与数据一致性保证。本章深入剖析三种主流协议:Cache Aside、Read/Write Through 与 Write Behind Caching,并给出明确的选型建议。
4.1 Cache Aside 旁路缓存
Cache Aside 是最常用的缓存策略,应用程序直接同时操作缓存和数据库。其核心原则是:读时回填,写时失效。
4.1.1 读流程
- 应用先查询缓存。
- 缓存命中,直接返回数据。
- 缓存未命中,查询数据库。
- 将查询结果写入缓存,并设置过期时间。
- 返回数据给调用方。
4.1.2 写流程
- 应用更新数据库。
- 使缓存中的对应键失效(删除或标记过期)。
关键陷阱:写操作必须先更新数据库,再删除缓存。若先删除缓存再更新数据库,在并发场景下会导致缓存中写入旧数据,造成长期不一致。
适用场景:读多写少、对一致性要求较高、可接受短暂缓存未命中的业务。例如用户信息、商品详情、配置数据。
4.2 Read/Write Through 读写穿透
Read/Write Through 将缓存抽象为数据访问的唯一入口。应用程序只与缓存交互,缓存负责与数据库同步数据。这种模式对应用层更友好,但缓存层承担了更多职责。
4.2.1 Read Through
- 应用请求数据时,直接访问缓存。
- 缓存命中则直接返回。
- 缓存未命中时,缓存组件自动从数据库加载数据,写入自身,再返回给应用。
- 应用无需感知数据库的存在。
4.2.2 Write Through
- 应用写入数据时,直接写入缓存。
- 缓存同步将数据写入数据库。
- 只有数据库写入成功,缓存才确认写入完成。
一致性保证:Write Through 在写入数据库成功之前不会返回成功,因此缓存与数据库始终强一致。代价是写入延迟增加,因为每次写操作都包含一次数据库同步写。
适用场景:对一致性要求极高、写入频率可控、可以接受写入延迟增加的系统。例如金融交易、订单状态、库存扣减。
4.3 Write Behind Caching 异步回写
Write Behind Caching(又称 Write Back)与 Write Through 类似,应用只与缓存交互。但区别在于:写入缓存后立即返回成功,数据库的更新被异步批量执行。缓存层会合并、延迟写入数据库。
4.3.1 核心流程
- 应用写入数据到缓存,缓存立即返回成功。
- 缓存将写操作记录到内部队列或日志。
- 后台线程或定时任务批量将数据刷新到数据库。
- 若缓存宕机,未刷入数据库的数据可能丢失。
4.3.2 关键权衡
| 维度 | Write Behind | Write Through |
|---|---|---|
| 写入延迟 | 极低(仅缓存写) | 较高(等待数据库) |
| 数据库压力 | 低(批量合并写入) | 高(每次写都落盘) |
| 数据一致性 | 最终一致性,有丢失风险 | 强一致性 |
| 实现复杂度 | 高(需队列、重试、幂等) | 中等 |
风险提示:Write Behind 在缓存节点宕机或网络分区时,未刷入数据库的写入数据会永久丢失。必须配合持久化队列(如 Kafka、WAL)和故障恢复机制使用。
适用场景:写吞吐量极高、对一致性要求不苛刻、可接受数据短暂丢失的业务。例如用户行为日志、点赞计数、访问统计、社交 Feed 流。
4.4 三种协议对比总结
| 协议 | 读一致性 | 写一致性 | 写入延迟 | 数据库压力 | 实现复杂度 | 典型场景 |
|---|---|---|---|---|---|---|
| Cache Aside | 最终一致(有窗口期) | 最终一致(先库后删) | 低 | 中 | 低 | 用户信息、商品详情 |
| Read/Write Through | 强一致 | 强一致 | 高 | 高 | 中 | 金融交易、订单状态 |
| Write Behind | 最终一致 | 最终一致(有丢失风险) | 极低 | 低(批量) | 高 | 日志、计数、Feed 流 |
4.5 选型决策建议
- 业务一致性要求极高(如支付、库存):优先选择 Read/Write Through,或 Cache Aside 配合分布式锁与版本号。
- 读多写少、允许短暂不一致(如商品展示):Cache Aside 是最简单高效的选择。
- 写吞吐量巨大、可接受最终一致(如日志收集):Write Behind 能大幅降低数据库写入压力。
- 混合使用:实际系统中常将三种协议组合。例如核心交易用 Write Through,非核心统计用 Write Behind。
治理契约视角:在分布式缓存一致性治理中,协议选择决定了后续的契约测试策略。Cache Aside 需重点测试缓存失效与回填的并发时序;Write Through 需验证缓存代理层的同步写入逻辑;Write Behind 则必须覆盖异步队列的持久化、重试与幂等性契约。