先这样答
结论是:用变更事件驱动增量索引,用双索引和别名完成原子切换,再让旧索引继续服务到切换完成。这样可以处理高频更新,不需要重建全库,也不会因为切换索引而中断读请求。
增量更新按文档处理。文档发生变更后,系统消费对应的变更事件。先在索引中删除这份文档的旧 chunk,再写入新 chunk。这里不重建整个知识库,只处理发生变化的文档。这样更新范围更小,也更符合高频变更的场景。
原子切换采用双索引。一个索引继续承接线上读请求,另一个索引接收更新并完成构建。新索引建完后,再一次性切换别名,让读请求从旧索引转到新索引。切换前,旧索引继续服务,切换期间也不停止服务。缓存按索引版本隔离,切换后旧版本缓存自然失效,避免新旧索引共用缓存。
面试官会怎么追问
-
「为什么要先删旧 chunk,再写入新 chunk?」
文档变更后,旧 chunk 已经不能代表当前文档内容。先删除旧 chunk,再写入新 chunk,可以让这份文档对应的索引内容完成替换。处理范围仍然限定在发生变化的文档,不需要重建全库。 -
「双索引为什么能做到原子切换?」
新索引在后台完成构建,线上读请求继续访问旧索引。新索引建完后,系统只做一次别名切换。读请求使用同一个访问入口,切换动作完成后就会转到新索引。 -
「切换索引时,线上请求和缓存怎么处理?」
切换期间,旧索引继续提供读服务,所以读请求不需要停下来等待新索引。缓存按索引版本隔离,旧索引和新索引不会共用同一份缓存。完成切换后,旧缓存会自然失效。
回答的坑
-
只说“增量更新”而不说明按文档先删旧 chunk、再写新 chunk,面试官无法确认更新边界。
-
只说“双写”或“重建索引”而不说明别名一次切换和旧索引继续服务,就没有回答原子切换与不停服。
同系列的题