元数据缓存会带来哪些一致性问题?
简化版
元数据缓存能减少每次请求查询控制面的开销,但分片迁移、Leader 切换或权限变更后,旧缓存会把请求发错节点、读旧副本甚至越过权限。治理要给元数据带单调 epoch/version,服务端拒绝过期写并返回刷新提示,客户端采用推送加 TTL/拉取兜底;敏感撤权不能只等待 TTL。
详细版
常见元数据包括 shard range、Leader、副本位置、schema、租户配额和权限。它们变化频率低但影响面大,因此适合缓存,也更怕旧值。
客户端携带 route_epoch=41 请求已迁移分片,而服务端当前是 42,应返回 STALE_EPOCH 和新位置,而不是在旧节点继续接收写。读请求是否允许旧路由,取决于旧副本是否仍有服务资格和一致性承诺。
更新策略通常是控制面推送失效/新版本,客户端定期拉取或 TTL 兜底,失败时指数退避。版本必须单调且按对象比较,不能只靠墙钟时间戳。
还要防缓存击穿和更新风暴:版本变更时分批刷新、singleflight 合并请求,并保留最后已知正确值,但安全配置失效时应 fail closed。
完整版教学
一、元数据为何值得缓存
若每个数据请求都先访问元数据服务,控制面会成为延迟和可用性瓶颈。客户端缓存路由后可直接访问数据节点,控制面只在变更时参与。代价是控制面真值与客户端视图之间出现传播窗口。
二、旧缓存会造成什么
路由旧可能写错节点;Leader 信息旧会把请求发给旧主;schema 旧会错误编码;权限旧可能让已撤权用户继续访问。不同元数据后果不同,不能统一用“允许 5 分钟 TTL”。
| 元数据 | 旧值后果 | 常见保护 |
|---|---|---|
| 分片路由 | 发错节点 | epoch 拒绝与重定向 |
| Leader | 超时或旧主写 | term/fencing |
| Schema | 解码失败 | schema id 与兼容检查 |
| 权限 | 越权风险 | 主动失效、短 TTL、服务端复核 |
三、版本号是安全底座
控制面为每次所有权变化生成单调 epoch。客户端请求携带已知 epoch,数据节点只接受与当前所有权兼容的版本;旧版本返回结构化错误,让客户端刷新后有限重试。
client(epoch=41) -> old owner
old owner(current=42) -> STALE_EPOCH(newOwner=B, epoch=42)
client refresh -> retry B
墙钟可能漂移或回拨,不适合作为唯一新旧依据。版本还应明确作用域:全局版本简单但更新风暴大,per-shard 版本细致但元数据更多。
四、推送、拉取与 TTL
推送收敛快但可能丢消息;拉取可靠但有周期延迟;TTL 简单却可能同时过期造成惊群。生产通常组合:推送作为快路径,版本不匹配按需拉取,后台周期校验做兜底。
假设 TTL 60 秒且 10 万客户端同时启动,若都整点刷新会压垮控制面。应加 10%~30% 抖动、singleflight 合并同一 shard 刷新,并用指数退避保护故障中的元数据服务。
五、迁移期间如何兼容双位置
分片迁移不是瞬时替换。旧节点先复制数据到新节点,追平后控制面提升 epoch 并切所有权;旧节点进入转发或拒绝状态,观察后再清理。请求中的 epoch 让两个节点知道谁有资格对外承诺。
直接同时允许两边写会形成双主,除非有额外共识或冲突协议。重定向应限制跳数,防止控制面异常导致 A、B 循环转发。
六、可用性与安全边界
控制面暂时不可用时,是否使用最后已知值取决于元数据类型。普通路由可在服务端 epoch 校验下继续尝试;权限撤销、密钥轮换等安全元数据过期时可能必须拒绝请求。
监控包括缓存命中率、元数据版本差、stale-epoch 错误、刷新延迟、推送丢失、控制面 QPS、重定向次数和循环。发布演练要覆盖推送丢失、客户端离线后恢复和控制面全不可用。
记忆钩子:缓存负责快,epoch 负责不写错;推送可以丢,服务端拒绝旧所有权这道防线不能丢。
七、常见误区与追问
- 误区:设置 TTL 就解决一致性。 TTL 只限制陈旧时间,窗口内仍可能写错位置或越权。
- 误区:收到推送就无需版本号。 推送可能乱序、重复或丢失,版本决定能否应用。
- 误区:旧路由最多多一次网络跳转。 若旧节点继续接受写,可能造成数据分叉。
- 追问:控制面挂了怎么办? 视元数据风险使用最后已知值,并依赖服务端 epoch/fencing 保护。
- 追问:如何避免刷新惊群? TTL 抖动、请求合并、分批推送和退避限流。
- 追问:权限缓存能否长 TTL? 高风险撤权应主动失效并由服务端复核,不能只靠自然过期。
八、加强记忆
元数据缓存的一致性闭环是“版本化真值、组合传播、请求带版本、服务端校验、失败刷新重试”。路由变化用 epoch 阻止旧 owner 写,安全元数据按更严格策略失效。答题要把性能快路径与安全最后防线分开说明。