在处理生产LLM应用中常见的大规模数据集和高查询量时,扩展单机向量搜索能力是必要条件。当您的索引包含数十亿向量或需要每秒处理数千次查询(QPS)时,将索引分散到多个节点就变得必要。这个过程被称为分片。
分片涉及将向量索引进行水平分区,将数据的子集(分片或分区)分散到不同的物理或虚拟机上。分片的主要目的有:
- 内存限制: 高维向量即使经过压缩,也会占用大量内存。十亿个768维
float32向量大约需要3TB内存(109×768×4 字节),远超大多数单台服务器的容量。分片使得索引能够驻留在集群的共享内存中。
- 计算并行: 搜索大型ANN索引计算量大。分散索引可以使搜索操作在多个节点上并行进行,从而减少查询延迟并提升整体吞吐量(QPS)。索引构建和更新也能从并行执行中获益。
- I/O吞吐量: 对于不能完全载入内存或需要频繁更新的索引,磁盘I/O可能成为瓶颈。分片将I/O负载分散到多个存储设备上。
高效的分片需要仔细考虑向量如何分配到分片以及查询如何路由。让我们来看看常见的策略。
随机分片
最直接的方法是随机分片。每个向量在摄入时,会根据一个确定性函数分配到一个分片,这个函数通常是其唯一ID的哈希值对分片数量取模。
- 机制:
shard_id = hash(vector_id) % num_shards
- 优点:
- 简单:易于实施和管理。
- 负载均衡:在假定良好的哈希函数和随机ID的情况下,倾向于将向量均匀分配到各分片,从而实现均衡的存储和计算负载。
- 缺点:
- 查询广播:由于向量是随机分布的,最近邻查询必须发送到每个分片。查询向量会与每个分片索引中的向量进行比较。
- 网络开销:广播查询会大幅增加网络流量。
- 聚合开销:来自所有分片的结果必须由协调器节点收集、合并并重新排序,这会增加延迟。
随机分片下的查询处理流程。查询必须广播到所有分片。
随机分片因其简单性通常作为默认或起点,但需要查询所有分片会限制对延迟敏感应用的扩展能力。
基于元数据的分片
一种常见模式,尤其是在多租户系统或数据具有不同分类的应用中,是根据与向量相关的元数据进行分片。
- 机制: 向量根据特定元数据字段的值(例如,
tenant_id、user_id、product_category、region、date_partition)分配到分片。
- 优点:
- 定向查询:如果查询包含针对分片元数据字段的过滤器(例如,“查找与
tenant_id = 123 的 X 相似的文档”),查询协调器只需将查询路由到包含该租户数据的特定分片。这能大幅缩小搜索范围、减少网络流量和聚合开销。
- 数据隔离:提供天然隔离,这有助于安全或合规性。
- 缺点:
- 潜在偏差:如果元数据值分布不均(例如,某个租户的数据量远超其他租户),分片的大小和负载可能会失衡(“热分片”)。这需要仔细监控和潜在的再平衡策略。
- 未过滤查询的广播:没有针对分片键进行过滤的查询仍然需要广播到所有分片,类似于随机分片。
- 模式依赖:分片策略与应用程序的数据模型紧密关联。元数据使用方式的改变可能需要不同的分片方法。
基于元数据的分片查询处理。查询仅根据过滤器路由到相关分片。
基于元数据的分片在查询经常对特定、分布良好的字段进行过滤时非常有效。这是SaaS应用中的一种常见模式。
基于向量的分片(聚类)
这种策略试图将语义相似的向量分组到同一个分片上。这样做的想法是,查询向量的最近邻居很可能位于同一分区内。
- 机制:
- 预处理:定期对向量数据的样本或全部数据运行聚类算法(如K-Means,或使用IVF式索引中的粗量化器),以识别出k个聚类中心,该k值是所需分片数量(或其倍数)。
- 分配:将每个向量分配到与其最近的聚类中心对应的分片。
- 路由:当查询到达时,识别与查询向量最近的聚类中心。仅将搜索查询路由到相应的分片。
- 优点:
- 缩小查询范围:理想情况下,查询只需发送到一个或少量分片,与随机分片相比,即使对于未过滤的查询,也能显著减少计算和网络负载。
- 潜在更低延迟:通过避免在不相关分片上进行不必要的计算,可以实现更低的延迟。
- 缺点:
- 实施复杂性:需要实施和维护一个聚类过程。聚类算法和聚类数量(k)的选择会影响效果。
- 维护开销:聚类需要随着数据分布的变化定期更新,这可能计算成本高昂。
- 聚类边界问题:位于两个聚类边界附近的向量,其真正的最近邻可能被分配到不同的分片,这可能会影响召回率,除非查询被路由到多个附近的分片。
- 潜在偏差:自然数据聚类的大小可能不均匀,导致分片不平衡。
基于向量的分片查询处理。查询被路由到与最近聚类中心对应的分片。
基于向量的分片在优化纯向量相似性搜索方面效果显著,但会增加系统设计和维护的相当大复杂性。
实施考虑
无论采用何种策略,实施分片都会带来一些系统层面的考量:
- 分片路由层: 需要一个组件(通常是查询协调器的一部分或专用路由器)来根据分片策略和任何查询参数(如元数据过滤器或查询向量位置)确定查询应发送到哪个分片。
- 结果聚合: 协调器必须从被查询的分片收集结果。这包括合并排序的邻居列表,可能根据全局一致的标准重新评分(如果分数在分片间不能直接比较,尽管距离度量通常可以),并选择最终的Top-K结果。这个聚合步骤会增加延迟。
- 分片管理: 确定最佳分片数量涉及平衡并行收益与管理开销和潜在的网络延迟增加。影响因素包括总数据大小、查询负载、每个节点的硬件资源和网络带宽。
- 动态再分片: 生产系统通常需要适应变化的数据量和查询模式。添加新分片以适应增长或重新平衡现有分片以处理偏差,需要复杂且通常是在线的(不停机)数据迁移程序。这些操作必须小心执行,以尽量减少停机时间或性能下降。技术可能包括拆分现有分片或使用一致性哈希环来管理分片分配。
选择合适的策略
最佳分片策略在很大程度上取决于您特定应用程序的需求:
- 查询模式: 查询通常是否包含元数据过滤器?如果是,基于元数据的分片通常非常有效。如果搜索是纯语义的且没有过滤器,则随机分片或基于向量的分片是主要选择。
- 延迟与复杂性: 随机分片最简单,但由于广播可能导致更高的延迟。基于向量的分片目标是更低的延迟,但会增加相当大的实施和维护复杂性。
- 数据特点: 是否存在适合分区的天然、分布良好的元数据字段?向量数据是否适合聚类?
- 系统架构: 多租户架构天然适合通过租户ID进行基于元数据的分片。
对于许多应用,基于元数据的分片在性能优势(在使用过滤器时)和可控复杂性之间提供了良好平衡,特别是当存在合适的元数据键时。随机分片可作为合理的参考起点。基于向量的分片通常保留用于将未过滤搜索的查询延迟降到最低作为主要目标,且工程投入合理的情况。
成功实施分片是构建能够处理互联网规模数据集和流量的向量搜索系统的重要一步,它构成了许多大规模RAG和语义搜索应用的骨干。