Redis 缓存更新:过期策略与数据库一致性

数据库已经修改,页面仍显示旧值,常见原因是缓存没有按同一个业务键失效。缓存提升读取速度,同时也增加了一份数据副本,需要写清什么时候可以使用旧值。

edyang · 2020-03-14

数据库已经修改,页面仍显示旧值,常见原因是缓存没有按同一个业务键失效。缓存提升读取速度,同时也增加了一份数据副本,需要写清什么时候可以使用旧值。

缓存旁路模式通常先读缓存,未命中再查数据库并填充;写入与缓存失效之间存在并发窗口。TTL 限制旧数据保留时间,却不能保证强一致。热点键同时过期还可能把大量请求打到数据库。

Redis 缓存更新:过期策略与数据库一致性:处理路径与验证条件

一、问题的范围与前提

数据库连接、事务、SQL 执行和数据结果应分别验证。一次连接成功不证明事务可写,也不证明原有查询在不同数据库上结果相同。应从实际业务入口取得证据,记录角色、数据库、事务范围与查询条件,再分析执行计划或连接池。

二、技术分析与方案取舍

写数据库与删缓存之间有竞争窗口,另一个请求可能读取旧数据后重新填入缓存。是否允许短暂旧值,要由字段用途决定。展示类数据可能允许有限滞后,权限和资金类状态则可能需要更严格路径。缓存键还应包含对象和必要版本,避免不同环境或不同查询条件共用。

测试包括并发写读、回源失败和旧值过期,不能只用顺序请求验证一遍。

测试数据先覆盖正常输入、边界值和并发条件。精度、空值、时间和关联约束需要固定规则,更新语句应处于明确事务中。对于会产生写入的试验,使用独立测试环境并准备恢复方法;只读执行计划也应核对查询是否会调用带副作用的函数。

三、实现与排查的顺序

  1. 确定缓存键与版本范围。
  2. 区分强一致与可短暂滞后字段。
  3. 设计写入后的失效顺序。
  4. 为热点回源设置有界并发。

按这个顺序保留中间结果,可以区分输入条件、处理过程和最终输出。前一阶段的条件不成立时,先解释对应错误,再继续后面的试验;单次返回成功不足以覆盖整条链路。

最小示例

1
2
3
4
缓存键:对象身份 + 字段语义 + 版本
读取:缓存命中 → 检查有效条件
未命中:受控回源 → 写入缓存
写入业务:提交主数据 → 执行约定的失效策略

这里说明通用缓存旁路关系,不代表强一致协议。缓存失效与回填并发需要专门测试,TTL 与锁各有失败窗口。将缓存故障和主数据故障区分后,才能决定允许旧值、降级或拒绝请求。

四、验证和结果解释

查询结果可以按主键集合、字段值和关联关系核验,不宜仅比较总行数。性能记录应同时保留参数、数据规模、缓存状态与并发条件。错误时检查服务端实际连接和活动事务,避免只观察另一台实例或另一份会话。

需要验证的结果 保留的对照 不能由此推出的结论
数据库修改后旧值有明确上限 固定输入与配置、对应输出 一次成功代表所有条件成功
并发回源不会覆盖新版本 中断前后状态与错误阶段 没有报错代表结果正确
缓存不可用时业务降级符合预期 恢复后的同条件复测 临时恢复代表根因已经消失

重试、刷新连接和改变数据库角色属于不同操作。异常后先确定处理结果,再决定重复执行;跨外部接口的业务还需要幂等和补偿。备份恢复与数据迁移必须演练,回到旧程序版本不自动恢复被修改的持久数据。

五、适用边界与结论

不要给所有缓存无差别设置很长 TTL,也不要把缓存命中率当正确率。订单与权限等数据需明确一致性要求,不能仅靠延长缓存时间改善速度。

这条路径把“确定缓存键与版本范围”与“为热点回源设置有界并发”连在一起,中间保留可复查的条件。实施时优先确认“数据库修改后旧值有明确上限”,再检查“缓存不可用时业务降级符合预期”;两者都满足,才能在当前样本与配置范围内评价方案。设备、数据或软件版本改变以后,相关假设需要重新验证。

参考资料