存储、索引与缓存的一致性
哪个系统是事实来源
| 系统 | 保存内容 | 可以丢弃重建吗 | 典型错误 |
|---|---|---|---|
| 业务数据库 | 订单、退款、库存等事实 | 依赖数据备份/确定性生成 | 用控制库账户执行生成 SQL |
| PostgreSQL Control Plane | 元数据、指标、关系、权限、版本、评测 | 需要备份恢复 | 直接改已发布指标 |
| OpenSearch | 文本、关键词、别名与值索引 | 可由控制资产重建 | mapping 未更新、旧列被召回 |
| Milvus | 各类语义向量 | 可按源数据与模型版本重建 | 维度变化还写旧 collection |
| Redis | 缓存、会话、配额计数、锁 | 缓存可丢;会话与任务需明确耐久要求 | 撤权后仍命中旧结果 |
Redis 同时服务 broker 与缓存时需要明确命名空间、容量和驱逐策略。生产是否拆实例由 V4 容量与可靠性验收决定,不能假设驱逐缓存对排队任务无影响。
发布一份 schema 的建议过程
text
采集业务库 → 控制库保存 snapshot(version=N, building)
→ Celery 构建 OpenSearch 与 Milvus 的 N 版本
→ 校验数量、版本与可检索性
→ 标记 N ready → 切换 active_version
→ 失效旧缓存 → 延迟清理旧索引这是本次提出的落地方案,不在三种数据库间建立分布式事务。通过版本快照和发布指针避免混用半成品;失败任务记录原因并幂等重试。V0 可先实现简单 job 表和明确重建命令,达到需要时再引入更复杂的 outbox。
缓存键必须反映查询语境
概念示例:
text
query:{datasource}:{data_version}:{schema_version}:{semantic_version}
:{policy_fingerprint}:{model_prompt_retriever_version}:{normalized_request_hash}真实在线数据通常没有每秒递增的完整 data_version,因此结果缓存还需要 TTL 或上游更新时间水位策略;固定 Benchmark 才能使用精确数据快照版本。
请求 hash 应包含时间窗口、参数、会话解析结果和结果限制。两个用户权限看似相同但列脱敏策略不同,也不能共享未经再次验证的缓存值。缓存命中仍记录 trace,并在撤权时失效。
Celery 的幂等不是可选装饰
一次元数据索引任务在 worker 断连后可能重新投递。用 datasource + snapshot_version + index_type 建立逻辑任务键,对任务状态和分批写入去重;重试不能自动推进发布指针。分布式锁使用持有者 token、有效期和安全释放,不能只依赖“执行完 DEL lock”。
失败实验
- 构建 N 版本 Milvus 时断连:查询继续使用 N-1,管理端看到失败任务。
- 发布指标新版本后立刻查询:本次响应各层都使用同一语义版本。
- 撤销用户成本列权限后重复同一问题:缓存不能泄露原结果。
- 清空一个派生索引:能够重建,不能通过手动写索引修补控制库缺失。
这些实验分别对应 V0-S05、V3-S02 和 V4-S02。