2. 缓存一致性概念

2.1 缓存一致性定义

缓存一致性(Cache Consistency)是指在分布式系统中,缓存层与后端数据库(主数据源)之间数据状态的等价关系。当数据库中的数据发生变更(INSERT / UPDATE / DELETE)时,缓存中对应的副本必须同步更新或失效,使得任何时刻从缓存读取的数据与数据库中的最新数据保持一致。

在 PostgreSQL 逻辑复制驱动缓存的场景中,缓存一致性直接决定了业务能否读到“正确”的数据。如果缓存与数据库出现偏差,轻则返回过期数据,重则引发脏读、重复提交、库存超卖等严重故障。

核心原则:缓存一致性不是“缓存与数据库数据完全相同”,而是“缓存数据在业务可接受的时间窗口内与数据库逻辑等价”。

2.2 读写缓存模型

根据缓存更新策略的不同,读写缓存模型主要分为以下三种:

模型 写入策略 读取策略 典型场景
Cache-Aside(旁路缓存) 应用先写数据库,再删除/更新缓存 先读缓存,未命中则读数据库并回填缓存 读多写少,容忍短暂不一致
Read-Through / Write-Through(穿透读写) 缓存层代理写入,同步写数据库和缓存 缓存层代理读取,缓存未命中由缓存层加载数据库数据 强一致性要求高,缓存与数据库耦合紧密
Write-Behind(异步回写) 应用只写缓存,缓存异步批量写回数据库 直接从缓存读取 写吞吐极高,可接受数据丢失窗口

PostgreSQL 逻辑复制驱动的缓存失效/更新通常采用 Cache-Aside + 订阅端回调 的混合模型:逻辑复制槽捕获数据库变更,通过解码输出到消费端,消费端再执行缓存删除或更新操作。

Cache-Aside + 逻辑复制缓存更新模型 应用服务 Redis / 本地缓存 PostgreSQL 逻辑复制解码 消费端(缓存失效器) 读缓存(先读) 写数据库(先写) WAL 变更事件 删除/更新缓存

2.3 最终一致性与强一致性对比

在缓存与数据库之间,一致性模型的选择直接影响系统可用性、性能和故障排查复杂度。

对比维度 强一致性(Strong Consistency) 最终一致性(Eventual Consistency)
定义 写入操作完成后,后续任何读取都能立即读到最新值 写入后允许短暂不一致,但保证在有限时间内所有副本收敛到最新值
实现方式 同步写缓存 + 分布式锁 / 事务性缓存 异步复制 + 过期失效 + 补偿机制
延迟 高(等待所有副本确认) 低(异步处理,不阻塞主流程)
吞吐量 低(串行化写入瓶颈) 高(批量异步写入)
故障影响 写入失败则整体不可用 短暂读到脏数据,但系统持续可用
PostgreSQL 逻辑复制场景 需同步复制 + 同步消费端确认,延迟极低但性能受限 异步逻辑复制 + 缓存 TTL + 重试队列,最常用方案
实践建议:在 PostgreSQL 逻辑复制驱动缓存的架构中,绝大多数业务场景选择最终一致性。强一致性通常只在金融交易、库存扣减等场景中局部使用,且需要配合同步复制和分布式事务。

最终一致性在逻辑复制中的典型时间线如下:

  1. 应用写入 PostgreSQL —— 事务提交成功,数据库已是最新状态。
  2. 逻辑复制解码延迟 —— WAL 日志被解码并传输到消费端,通常毫秒级,但可能因网络或消费积压而增大。
  3. 消费端执行缓存失效 —— 删除或更新缓存中的旧数据。
  4. 缓存收敛 —— 后续读请求命中新数据或重新从数据库加载。

这个时间窗口(步骤 1 → 步骤 4)就是“不一致窗口”。窗口大小取决于逻辑复制的延迟、消费端的处理速度以及缓存的 TTL 策略。

最终一致性时间线:不一致窗口 时间 T1 T2 T3 写入数据库 解码 & 传输 缓存失效 不一致窗口(Stale Read 风险区) 旧缓存数据仍可被读取,新数据尚未生效