当每天新增 100 万篇文档时,如何设计分层索引避免全量重建?
解读
面试官想验证三件事:
- 对海量增量数据的实时/准实时处理能力;
- 对向量+关键词混合检索的架构经验;
- 对国内合规、成本、容灾三要素的平衡意识。
每天 100 万篇 ≈ 11.5 篇/秒峰值,若每篇 2 k token,仅向量增量就达 2.3 B token/天,全量重建一次千亿级索引既烧钱又违法(《生成式 AI 管理办法》要求内容可溯源,不能“一删了之”)。因此必须给出**“增量分层、冷热分离、版本回退”**的方案。
知识点
- 分层索引(Hierarchical Index):把索引拆成热、温、冷三层,热层毫秒级、温层分钟级、冷层小时级,各自采用不同存储与召回策略。
- 增量段(Segment)+ 版本链:借鉴 Lucene 的 segment 机制,新增文档只写新段,通过版本号做快照隔离,老段后台合并,保证读写无锁。
- 向量量化与压缩:国内常用阿里云 PASE、腾讯云 Vearch、Milvus 2.3+,支持IVF_PQ、HNSW_PQ,可把 768 维 float32 压到 96 维 int8,内存降 8 倍,单台 512 G 内存可扛 2 亿 768 维向量。
- 关键词倒排热更新:对标题、实体、摘要建倒排+跳表,使用RoaringBitmap存储 docID,增量插入直接内存映射,延迟 <100 ms。
- 时间窗口分片:按天级分片(shard_20240625)存储,配合TTL 策略,90 天前冷数据转 OSS+S3 协议低频存储,节省 70% 成本。
- 双写+回退:写入时先写WAL(Kafka/Pulsar),再写热层,成功后更新ZK/Etcd 版本指针;若模型效果回退,可秒级切回旧版本,满足国内**“可撤销”**合规要求。
- Merge Policy:国内大厂实践采用**“大小段分层合并”:<10 万 docs 为小段,每 30 分钟合并一次;>100 万 docs 为大段,每天凌晨低峰期合并,合并时过滤已删除 doc** 并重新计算 PQ 码本,避免写放大。
- 分布式一致性:使用Raft Group管理 segment 元数据,一写多读模型,保证RPO=0、RTO<30 s。
答案
“我会把索引拆成热、温、冷三层,热层只存当天数据,用内存 HNSW + 倒排组合,延迟 10 ms 内;温层存近 7 天,用磁盘 IVFPQ,延迟 50 ms;冷层存 90 天全量,用OSS + 压缩 PQ,延迟 200 ms 可接受。
新增 100 万篇文档时,先写Kafka 队列,Flink 作业解析后双写:
- 热层:把向量 768 维用PQ-96 压缩,倒排只存标题与 5 个关键词,segment 大小 10 万 docs,写完立即在ZK 注册新版本号;
- 温层:每 30 分钟把热层 segment 滚动合并,重新训练 PQ 码本并写入温层 Milvus 集群;
- 冷层:每天凌晨把温层大段合并后转冷存,同时把删除位图一并打包,保证溯源。
整个流程无全量重建,通过版本链 + 快照隔离实现秒级回退,存储成本降低 60%,单集群可扛 50 亿向量,满足国内等保三级与**《生成式 AI 管理办法》**要求。”
拓展思考
- 如果业务要求实时删除涉政敏感文档,如何做到物理删除 <1 分钟且不影响合并流程?
答:在热层引入**“墓碑标记 + 布隆过滤器”,合并时直接跳过墓碑 doc,并把docID 加入全局黑名单 Bitmap**,查询层先过滤再召回,实现逻辑删除实时、物理删除延迟合并。 - 当索引节点跨可用区部署,网络分区导致 Raft 选主抖动,如何保障写入可用性?
答:采用**“双通道”机制:主分区正常写,备分区降级为“只写热层不落温层”,分区恢复后通过WAL 对齐补齐温层,保证CAP 中牺牲 C 保 A**,符合国内**“先上线后补数据”**的务实风格。