Milvus 架构:基于存算分离的分布式向量数据库

Milvus 架构的核心是存算分离:proxy 和各类 worker 都是无状态的,所有 segment 和索引以对象存储为准。作为分布式向量数据库,它把向量数据、写入和检索分散到多个节点上,各自按需扩展。本文讲清分层、写入与查询流程,以及把规模推到数百亿向量的量化和磁盘索引。

  • Apache-2.0,GitHub 40K+ star
  • 可扩展到数百亿向量
  • 对象存储是唯一数据源
  • IVF_RABITQ 压缩比 1:32
  • partition key 支持百万级租户
计算节点不持有对象存储无法重建的数据,所以读、写、建索引可以分别扩缩。
计算节点不持有对象存储无法重建的数据,所以读、写、建索引可以分别扩缩。
Milvus 与 Zilliz Cloud 用户
  • Salesforce
  • Walmart
  • Reddit
  • eBay
  • NVIDIA
  • Roblox
  • Filevine
  • Shell

Milvus 架构详解:分布式向量数据库分哪几层?

Milvus 分四层,各层独立扩展、独立容灾。新写入的流式数据由 streaming node 处理,已封存的历史数据由 query node 和 data node 处理,写入和检索不抢同一批机器,相当于天然的读写分离。

数百亿Milvus 设计支持的向量规模查看来源
300 亿+Filevine 在 Zilliz Cloud(托管 Milvus)上管理的向量数查看来源
100 亿+可灵 AI 最大开源 Milvus 单集群向量数,400+ 个 query node查看来源
Milvus 向量数据库架构:组件与职责
组件层职责何时扩容
Proxy(无状态)接入层校验请求、按 shard 路由、归并结果连接数或请求量上升
Coordinator协调层拓扑、DDL、时间戳、负载均衡、任务调度;全局单活不横向扩展,备用实例做 HA
Streaming NodeWorker持有 shard 的 WAL、定序写入、检索 growing 数据写入吞吐上升
Query NodeWorker加载 sealed segment 和索引、执行检索加载数据量或 QPS 上升
Data NodeWorkercompaction 与建索引建索引或 compaction 积压
对象 / WAL / 元数据存储存储层segment 与索引;预写日志;schema 与 checkpoint数据量上升

向量数据库的存算分离是怎么实现的?

在 Milvus 里,对象存储是唯一的数据源:sealed segment、索引文件和日志快照都落在 S3、MinIO、Azure Blob 或 Google Cloud Storage 上。worker 节点无状态,新加的 query node 直接从对象存储拉 segment,扩容不需要在节点之间搬数据。

预写日志也是同样思路。从 Milvus 2.6 起,Woodpecker 把 WAL 直接写进对象存储、不依赖本地盘,取代 Kafka 或 Pulsar;Milvus 3.0 还支持把 Woodpecker 作为独立服务部署。

  • 读、写、建索引分别扩容,缺哪类节点只加哪类。
  • 节点宕机不丢数据,coordinator 把它的 segment 或 shard 重新分配。
  • 持久数据放在便宜的对象存储上,计算层保持弹性。
  • 用 resource group 隔离业务,不必拆成多个集群。

Milvus 的写入流程和查询流程是怎样的?

写入路径与检索路径在 segment 处衔接。新数据先进入 WAL 和 growing segment,何时可被某次查询看到取决于一致性级别。segment 封存并落到对象存储后,由 data 节点建索引、query 节点加载;compaction 在后台合并数据并处理删除。

  • 查询流程:proxy 把请求发给每个 shard 的 streaming node,后者检索自己的 growing segment,并把 sealed segment 的子任务分发给 query node。
  • 各节点返回本地 top-k,先按 shard 合并,再在 proxy 跨 shard 合并。
  • 一致性级别按请求指定:Strong、Bounded(默认)、Session、Eventually。
Milvus 写入流程:streaming node、data node、query node 各自的职责(按架构概述文档)
阶段发生了什么组件
路由proxy 校验请求,按主键哈希到 shard(vchannel)Proxy
写日志分配时间戳,追加到 WAL,写入即确认Streaming node → WAL 存储
Growing segment驻留内存;可见性由一致性级别决定Streaming node
封存与落盘达到阈值后变为不可变的 sealed segment,写入对象存储Streaming node → 对象存储
建索引与 compaction构建索引;合并小 segment;落实删除Data node
加载加载 sealed segment 和索引,释放对应的 growing 数据Query node

Milvus 集群扩容:读、写、建索引怎么分别扩?

写入经 proxy、streaming node 和 WAL 接收;growing 与 sealed 数据按查询的一致性级别共同提供检索。封存数据在对象存储中持久化,由 data 节点建索引、query 节点加载,各阶段可分别扩缩。

向量数据库的分片、副本与 resource group:按瓶颈选扩容手段
瓶颈手段
写入吞吐增加 shard(每个 collection 最多 16)和 streaming node
建索引跟不上写入增加 data node
数据超出 query node 内存量化或磁盘索引、mmap、分层存储,或加 query node
检索 QPS在不同 query node 上增加内存副本
业务互相干扰用 resource group 把 query node 绑定到指定 collection
租户很多partition key:一个 collection 承载百万级租户

十亿级向量检索,用哪些量化索引省内存?

float32 原始向量每条占 维度 × 4 字节,HNSW 还要加图结构开销。到了十亿级,内存就是成本大头。Milvus 提供多档压缩比的向量量化,多数都支持 refine:先用压缩向量粗排,再用更高精度数据重排,把召回率补回来。

Milvus 向量索引:内存占用与适用场景(数字来自 Milvus 文档)
索引向量内存占用适用场景
HNSW(FP32)完整原始向量 + 图连接数据放得进内存,追求最低延迟和最高召回
HNSW_SQ(SQ8、SQ6、SQ4U、FP16、BF16)每维 8、6、4 或 16 bit;SQ8 比 FP32 省 75%保留 HNSW 速度,同时压缩内存
HNSW_PQ / HNSW_PRQPQ 压缩 4–32 倍;PRQ 加残差量化提精度内存预算紧但仍想用图索引
IVF_SQ8 / IVF_PQ每维 1 字节 / PQ 码大批量、高吞吐,建索引更便宜
IVF_RABITQ每维 1 bit,压缩比 1:32;可用 SQ6、SQ8、FP16、BF16、FP32 做 refine极致压缩;内存不够时替代 IVF_FLAT 或 IVF_SQ8
GPU_CAGRA / GPU_IVF_PQ数据加载进 GPU 显存GPU 上的高吞吐、高召回检索

RaBitQ(Gao & Long,SIGMOD 2024)为 1-bit 编码给出理论误差界;在支持 AVX-512 VPOPCNTDQ 的 CPU 上更快。

数据比内存大怎么办?DiskANN 磁盘索引与冷热分层

压缩后仍放不下时,可以把索引放到本地 NVMe,或者把冷数据留在对象存储。Milvus 文档的建议是:内存只放得下约四分之一原始数据时,考虑 DiskANN。

Milvus 的磁盘索引与冷热分层选项
方案内存里放什么其余数据在哪适用场景
DiskANNPQ 码,默认为原始向量的 1/8Vamana 图和原始向量在 NVMe SSD十亿级检索,延迟稳定
AISAQ(Milvus 2.6.4+)接近零内存;可选 PQ 缓存全部索引结构在 SSD普通服务器上的超大规模数据;RAG、离线检索
mmap只有热页字段和索引通过内存映射放本地盘数据略超内存;量化 IVF + mmap
分层存储 Tiered Storage(Milvus 2.6.4+)元数据 + 缓存的热 chunk对象存储,按需拉取,冷了就淘汰超出单节点内存或磁盘的 collection;关键字段可预热

Milvus 能扩展到多大?

Milvus 单机版(Standalone)和 Milvus 分布式部署(Distributed)的区别只在于是否把同一套组件分散到多台机器。单个 collection 的实体数不设上限,容量随 segment、shard 和节点增长。下面的默认值来自 Milvus 文档和配置。

Milvus 规模:文档中的默认值与上限
项目默认值 / 文档规模
向量规模数百亿
每集群 collection 数65,536(maxCollectionNum,可调)
每集群 database 数64
每 collection partition 数1,024
partition key 租户数百万级,单个 collection
每 collection shard 数16
向量维度32,768

常见问题

什么是分布式向量数据库?

把数据分片、把写入、建索引和检索分散到多个节点的向量数据库,每种能力都能靠加机器扩展。Milvus Distributed 是基于共享对象存储的 Apache-2.0 开源实现。

向量数据库为什么要做存算分离?

持久数据放在对象存储里,计算节点只做无状态的缓存和执行。加 query、streaming 或 data node 都不用搬数据,节点坏了直接替换,不用修复。

Milvus 的写入流程和查询流程是怎样的?

写入:proxy → streaming node → WAL,随后进入 growing segment 即可检索;封存后写入对象存储,data node 建索引,query node 加载。查询:proxy → streaming node(增量数据)和 query node(sealed segment)→ 合并 top-k。

Milvus 的分片和分区有什么区别?

shard 按主键哈希切分写入通道(每个 collection 最多 16 个),各由一个 streaming node 持有,决定写入并行度;partition 是按业务含义划分的数据子集(每个 collection 最多 1,024 个),查询时指定 partition 可缩小扫描范围。partition key 则让某个字段自动映射到 partition,一个 collection 承载百万级租户。

十亿级向量检索需要多少内存?

float32 原始向量每条占 维度 × 4 字节,另加索引开销。SQ8、PQ、RaBitQ 等量化,加上 DiskANN 和分层存储,都能减少必须常驻内存的部分;可用 milvus.io/tools/sizing 估算。

DiskANN 和 HNSW 有什么区别,怎么选?

原始向量放得进内存、延迟最敏感时用 HNSW。数据远超内存时用 DiskANN:图和原始向量在 NVMe SSD 上,内存里只放 PQ 码。

Milvus 有哪些一致性级别?

四种,按 search 或 query 请求指定:Strong 读最新数据;Bounded(默认)允许短暂的陈旧窗口;Session 保证同一客户端读到自己的写入;Eventually 以新鲜度换最快的读。

不想自己运维集群?

Zilliz Cloud 提供全托管 Milvus,API 与 MilvusClient 一致,节点数、升级和分层存储都由平台负责。Filevine 在上面管理着 300 亿+ 向量。