← 返回题目列表

RAG 索引如何增量更新?

中等 第 24 / 29 题 更新于 2026/09/18
RAG增量索引CDC数据一致性

简化版

增量更新应以稳定 document_id 和单调 source_version 为基础,将新增、修改、删除与权限变化转成幂等事件。修改时只重算受影响 chunk,但 chunker 或 embedding 版本改变需新索引全量回填。采用 snapshot+delta、tombstone 删除、双索引切换和周期对账,确保查询看到一致版本且可回滚。

详细版

管线从 CDC/Webhook/定时扫描获取事件,抓取源内容并算 hash;内容未变只更新元数据,变更则解析、切块、embedding 后 upsert,新版本成功后再淘汰旧 chunk。删除先写 tombstone 立即屏蔽,再异步物理清理。事件携带 version,消费者忽略重复和乱序旧事件。

监控 source-to-index lag、队列积压、失败/死信、孤儿 chunk、版本覆盖率和查询陈旧率。大版本迁移时旧索引持续服务,新索引按快照回填并同时消费 delta,追平后 shadow 比较召回,再原子切 alias;不要在原索引中混用不同 embedding 空间。

源快照 ----> 新索引回填 ----┐
变更日志 -> 新旧双写 delta --┼-> 追平/校验 -> alias切换 -> 保留旧索引回滚

完整版教学

一、为什么不能每次全量重建

百万文档中每天只改 1%,全量解析和 embedding 会浪费 99% 计算,还让新内容长时间不可见。增量索引只处理变化,降低成本与更新延迟。代价是需要处理乱序、重复、删除和部分失败。

系统要明确一致性 SLA:新闻可能要求分钟级,内部手册可小时级,权限撤销则可能要求秒级。更新策略由业务时效和安全风险决定,而不是统一 cron 周期。

二、稳定 ID 与版本是基础

document_id 在移动或改名后仍应稳定,source_version 随每次变更单调增加。chunk_id 可由 document_id + version + chunk_ordinal/content_hash 生成。事件包含 operation、版本、时间和内容位置。

if event.version <= indexed.version: ignore
else: build new version -> commit -> retire old version

记忆钩子:增量系统不怕消息重复,怕的是没有版本;有单调版本,重放和乱序都能变成幂等判断。

三、修改时怎样避免半新半旧

一个文档拆成 20 块,若逐块覆盖,查询可能同时看到 8 个新块和 12 个旧块。可先写入不可见的新 document_version,全部成功后原子切 active_version,再异步删旧块。向量库不支持事务时,用查询过滤 active manifest 实现逻辑原子性。

操作安全顺序
新增全部块完成后发布
修改写新版本→校验→切 active→删旧
删除tombstone 屏蔽→物理清理
权限撤销deny 先行→索引/缓存失效

失败版本保留状态但不可见,便于诊断和重试。

四、如何判断哪些 chunk 要重算

内容 hash 未变时可复用 embedding,只更新标题、权限或时间元数据;局部修改可按结构节点 hash 找变化块。但章节插入会使 ordinal 整体变化,基于内容/节点稳定 ID 比纯序号更好。相邻上下文或 overlap 改变时,附近块也需重算。

若 chunker、Tokenizer、清洗或 embedding 模型升级,旧新向量含义改变,通常不能局部混用。创建新 index_version 全量构建更安全。索引 manifest 记录所有处理组件版本。

五、Snapshot 加 Delta 如何无缝迁移

在时刻 T 获取源快照和变更日志 offset。新索引回填快照,同时缓存/消费 T 之后 delta;回填完成后继续应用 delta 直到 lag 接近零。随后对文档数、版本和检索结果校验,再切查询 alias。

如果不记录 offset,回填期间发生的修改可能永久漏掉。切换前短暂 barrier 或使用一致性位点,确保没有缝隙。旧索引保留一段时间,以便新模型召回异常时快速回滚。

六、删除为何需要 Tombstone

对象存储、向量库和缓存删除可能异步。tombstone 在查询过滤层立即声明某 document/version 不可见,阻止删除窗口泄露;后台再清理向量、文本、缓存和引用。tombstone 也带版本,防迟到的旧 upsert 复活文档。

物理清理完成后不能过早删除墓碑,应超过消息最大延迟/保留期。合规删除还要覆盖备份和日志,并记录完成证据。内容删除与权限撤销共享 fail-closed 原则。

七、如何监控和对账

关键指标包括事件到达/应用 lag、吞吐、重试、死信年龄、源文档与 active 索引数差、embedding 版本覆盖、孤儿块和 tombstone 堆积。平均 lag 会掩盖卡住的单文档,要看 P95/P99 与最大值。

周期全量对账比较 source manifest 与 index manifest,发现漏事件后补发。可设置 canary 文档定期新增、修改、删除,端到端测可见时间。查询日志带 index_version 与 document_version,才能定位陈旧回答。

八、常见误区与追问

  • 误区:定时全量扫描就是增量更新。 它可发现变化,但仍需版本、幂等和原子发布处理并发。
  • 误区:新模型向量可以逐条写进旧索引。 不同 embedding 空间不可比较,应双索引迁移。
  • 误区:向量删除成功就完成删除。 文本、缓存、引用和备份也需处理,tombstone 先阻断查询。
  • 追问:如何防乱序事件覆盖新版本? 用源单调 version 做 compare-and-set。
  • 追问:回填时如何不漏新修改? 快照绑定日志 offset,同时消费之后 delta,追平再切换。
  • 追问:何时局部重算? 处理版本相同且能稳定识别受影响结构块时,否则全量新索引。

九、加强记忆

增量索引可记成“稳 ID、单调版、先新后切、删除先挡、升级双建、周期对账”。事件幂等处理,文档整版原子可见;snapshot 回填与 delta 追平后切 alias;tombstone 防删除窗口;模型或 chunker 变化走新索引。这样才能同时做到新鲜、完整、可回滚。