3. 向量检索系统架构:从单机到分布式

聊到向量检索系统架构,我习惯先把它拆成两个维度来看:存储与计算的耦合方式,以及索引构建与查询的时序关系。说白了,就是你的数据放在哪、怎么算,以及什么时候建索引、什么时候查。

这一章我们重点讲四种架构模式。它们不是互斥的,实际项目中往往是组合使用。我见过不少团队一上来就搞分布式,结果单机都没调明白——嗯,咱们还是从基础开始。

3.1 单机向量检索架构

单机架构是最朴素的形式。所有向量数据存在一台机器的内存或本地磁盘里,检索进程也跑在同一台机器上。

核心特征:索引加载后常驻内存,查询请求直接在本进程内完成距离计算和 Top-K 归并。

我曾经在早期的一个推荐系统项目里用过这种架构。当时向量规模只有 200 万,128 维,用 HNSW 索引,单机 64GB 内存完全扛得住。QPS 能做到 3000 左右,P99 延迟 5ms 以内。

单机架构的优缺点很明显:

维度 说明
优点 部署简单、延迟极低、无网络开销、调试方便
缺点 容量受限于单机内存、单点故障、无法水平扩展
适用场景 千万级以内向量、对延迟敏感、可用性要求不苛刻

我的建议:如果向量规模在 500 万以下,优先考虑单机。别为了「分布式」而分布式,单机能解决的问题不要引入复杂度。

3.2 分布式向量检索架构

当向量规模突破千万甚至亿级,单机就撑不住了。这时候需要把数据和计算分散到多台机器上。

分布式架构通常有两种分片策略:

  • 数据分片(Sharding):按某种规则(如哈希、聚类)把向量分配到不同节点,每个节点只负责自己那部分数据的索引和检索。
  • 副本分片(Replication):每个分片保留多个副本,提升读吞吐和可用性。

我记得有一次帮一个电商团队做以图搜图,向量规模到了 5 亿。单机 HNSW 索引光加载就要 2 小时,内存根本放不下。最后我们用了 16 个节点做分片,每个节点只管理 3000 多万向量,查询时广播到所有分片再合并结果。

注意:分布式检索的瓶颈往往不在计算,而在「合并」。每个分片返回 Top-K 后,协调节点要做 K×N 个结果的全局排序。分片越多,合并开销越大。

分布式架构的核心组件:

  • 协调节点(Coordinator):接收查询,广播到各分片,合并结果。
  • 数据节点(Data Node):持有分片索引,执行本地检索。
  • 元数据服务:管理分片路由、节点状态、索引版本。

3.3 索引构建与查询分离

这是我在生产环境中特别推崇的一种模式。你想想看,如果建索引和查索引用同一批资源,建索引时 CPU 跑满,查询延迟就会飙升。

分离架构的核心思路:

  • 构建集群:专门负责从原始向量数据构建索引文件,产出后推送到存储层。
  • 查询集群:从存储层加载已经构建好的索引文件,只负责检索。
  • 共享存储:构建好的索引文件放在分布式文件系统(如 HDFS、S3、NFS)上,查询节点按需加载。

这样做的好处:构建和查询的扩缩容可以独立进行。大促时只扩查询节点,平时只保留少量构建节点做增量更新。

我曾经踩过一个坑:构建集群和查询集群共用同一批机器,结果凌晨做全量索引重建时,白天的查询延迟从 5ms 飙到了 200ms。后来改成分离架构,再也没出现过这种问题。

3.4 实时索引与批量索引

索引的更新方式决定了系统的数据新鲜度。这里有两种典型策略:

类型 更新方式 延迟 吞吐 典型实现
批量索引 定时全量/增量重建 分钟~小时级 高 Spark 批量构建 HNSW/IVF
实时索引 逐条插入/删除 秒级 中 Faiss 在线 IVF、HNSW 动态插入

批量索引适合离线场景,比如每天凌晨把当天的增量数据合并到全量索引里。实时索引适合在线场景,比如用户刚上传的图片要立刻能被搜到。

我个人的习惯是:两者结合。用实时索引处理最近几分钟的新数据,用批量索引覆盖全量历史数据。查询时走「实时+批量」两路召回,再合并去重。

避坑指南:实时索引的写入性能会随着索引大小下降。我曾经遇到过 HNSW 实时插入到 1000 万条后,单条插入延迟从 1ms 涨到了 50ms。后来我们限制了实时索引的大小,超过阈值就触发批量重建。

3.5 架构选型对照

最后给一张我常用的选型对照表,方便你快速决策:

场景 推荐架构 理由
向量 < 500 万,延迟敏感 单机 + 批量索引 简单、低延迟、易维护
向量 500 万~1 亿,高可用 分布式 + 索引查询分离 可扩展、构建不影响查询
向量 > 1 亿,高吞吐 分布式 + 分片 + 批量索引 水平扩展、合并可控
需要秒级数据新鲜度 实时索引 + 批量索引混合 兼顾新鲜度和全量覆盖
向量检索系统架构总览 单机架构 数据 & 索引同机 内存常驻 进程内检索 适用:<500万向量 分布式架构 数据分片 + 副本 协调节点合并 水平扩展 适用:>500万向量 索引查询分离 构建集群独立 查询集群独立 共享存储 适用:高可用场景 批量索引 定时全量/增量重建 延迟:分钟~小时级 吞吐:高 实现:Spark + Faiss 实时索引 逐条插入/删除 延迟:秒级 吞吐:中 实现:HNSW动态插入 实际生产:实时索引 + 批量索引混合使用,两路召回后合并

这张图把四种架构的关系画清楚了。上面是三种系统架构,下面是两种索引更新方式。实际项目中,你可以从左上角开始选,规模大了往右走,新鲜度要求高了往下走。

嗯,架构选型没有银弹。我见过用单机扛了 2 亿向量的团队——他们用了压缩量化,牺牲了一点精度换容量。也见过分布式只有 100 万向量的团队——纯粹为了练手。关键还是看你的业务场景和资源约束。