业务如何判断能否接受读旧数据?
简化版
判断能否读旧要看旧值会不会导致不可逆错误,而不是只看“延迟几秒”。 展示、推荐等可容忍有界陈旧;余额扣减、权限撤销、唯一约束、库存确认等决策通常必须读取权威状态或再次校验。 应为每个接口定义最大陈旧时间/版本、降级行为和用户提示,并监控实际陈旧度。
详细版
评估四点:数据用途是展示还是决策,错误后果是否可逆,陈旧窗口多大,是否有提交前权威校验。 商品详情可读 30 秒旧缓存,但下单价格和库存应在写入阶段校验。 黑名单若读旧会放过风险请求,应失败关闭或缩短陈旧上限。
系统返回数据版本或已应用水位,路由根据 maxStaleness 选择副本;generatedAt 只能表示缓存生成时间,不能单独证明它落后源端多少。
超过阈值时可转主库、等待追平、返回处理中或降级,而非静默继续。
SLO 同时看陈旧年龄、旧读比例和业务错误影响。
完整版教学
一、先区分展示与决策
新闻列表旧 10 秒通常只影响新鲜度。 用旧余额批准转账可能造成真实损失。 同一份数据在不同接口中的容忍度可以完全不同。
能否读旧由读结果驱动的动作决定,不由数据表名称决定。
二、风险评估矩阵
| 维度 | 低风险 | 高风险 |
|---|---|---|
| 用途 | 展示、推荐 | 授权、扣款 |
| 后果 | 可刷新恢复 | 不可逆损失 |
| 校验 | 后续有权威确认 | 直接作为最终决策 |
| 窗口 | 分钟可接受 | 秒级也不可接受 |
业务 owner 需要签署具体阈值。
三、有界陈旧
用版本差或复制 lag 表达“落后源端多少”;若业务约束的是缓存刷新周期,还可单独限制数据年龄,但两者不能混为一谈。
version_gap = source_high_watermark - replica_applied_watermark
time_lag = source_high_watermark_time - replica_applied_watermark_time
acceptable = version_gap <= max_version_gap
&& time_lag <= max_time_lag
&& replica_applied_watermark >= required_watermark
数据长期没有发生更新时,提交时间很早不等于副本陈旧;物理时间水位不可可靠比较时,应使用日志 offset、快照序号或逻辑版本。 阈值应写进接口契约。
四、提交前再校验
浏览商品可读缓存中的旧价格。 创建订单时回权威定价服务确认价格和库存。 这种“读路径弱、写决策强”的组合兼顾性能与正确性。 校验失败要让用户确认变化,不能静默按旧值成交。
五、安全类数据
权限授予读旧可能少权限,权限撤销读旧却可能继续放行。 两种错误方向风险不对称。 可对撤销列表失败关闭,对普通展示失败开放。 策略按操作与失败方向设计,不能全局一个 fail-open。
六、降级顺序
副本过旧时先尝试进度更高节点或主库。 在 deadline 内等待追平。 仍无法满足时返回明确错误、处理中或安全默认值。 不要在接口宣称强一致的同时静默返回旧缓存。
七、观测和演练
响应可带 version/generatedAt 供内部诊断。 监控 stale age、转主比例、等待时间、超阈值拒绝与业务损失。 演练副本延迟、主库不可用和时钟异常。 阈值变化走配置审批和灰度,防止为降告警随意放宽。
八、常见误区与追问
- 误区:配置和商品都能统一容忍 5 分钟。 用途不同导致风险不同。
- 误区:读旧只影响页面显示。 它可能驱动授权或资金决策。
- 误区:缓存有 TTL 就是有界陈旧。 数据更新后缓存年龄不等于源版本差。
- 误区:高可用要求永远 fail-open。 安全场景可能必须失败关闭。
- 追问:如何量化陈旧? 时间年龄、版本差或日志水位。
- 追问:如何兼顾性能? 展示读副本,最终写入前权威校验。
- 追问:超过阈值怎么办? 转主、等待或明确降级,不能静默违约。
九、加强记忆
- 看读结果是否驱动不可逆决策。
- 用时间或版本定义最大陈旧。
- 展示可弱,提交前可强校验。
- 安全数据按错误方向选择 fail-open/closed。
- 超阈值时明确降级并监控真实影响。