Milvus 架构与原理

四层架构、核心组件、实现原理与写入 / 查询 / 建索引三大核心流程

云原生 存储计算分离 日志即数据 MPP 并行

①架构总览:一条核心设计哲学

「日志即数据」+ 存储计算彻底分离。 Milvus 把一切状态变更都先写进日志(消息队列),再异步落盘到对象存储;计算节点无状态、可随时扩缩。整个系统按职责切成四层,每层独立扩展、独立容灾。
接入层 Access Proxy(无状态网关) 协调服务 Coordinator RootCoord · QueryCoord DataCoord · IndexCoord 系统的「大脑」 执行节点 Worker QueryNode(检索) DataNode(落盘/合并) IndexNode(建索引) 存储层 Storage etcd(元数据) · Pulsar/Kafka(日志) S3 / MinIO(对象存储)

数据流自上而下:请求经 Proxy 入系统,协调服务分配任务,Worker 执行,状态最终沉淀到存储层;控制流(元数据、调度)与数据流分离。

②四层组件逐一拆解

接入层(Access Layer)

Proxy(无状态)

系统唯一门面:校验请求、路由、把各 QueryNode 的中间结果做全局归并(reduce/聚合)后返回。前面通常挂 Nginx / K8s Ingress 做负载均衡。

协调服务(Coordinator Service)—— 系统的大脑

RootCoord

处理 DDL/DCL(建/删 Collection、Partition、Index),维护中心授时 TSO,推进时间窗口。

QueryCoord

管理 QueryNode 拓扑与负载均衡,负责把「增长段」交接成「密封段」。

DataCoord

管理 DataNode 拓扑、维护数据元信息,触发 flush / compaction 等后台操作。

IndexCoord

管理 IndexNode 拓扑,下发并跟踪索引构建任务、维护索引元信息。

执行节点(Worker Node)—— 系统的四肢

QueryNode

订阅日志 broker 获取增量(growing segment),从对象存储加载历史段,执行标量+向量混合检索。

DataNode

订阅日志、处理写入/删除,把日志快照打包持久化到对象存储,执行 compaction。

IndexNode

执行索引构建。资源密集,可 serverless 模式按需拉起,不必常驻。

存储层(Storage)—— 系统的骨骼

组件职责典型选型
元数据存储 MetaSchema、节点状态、消费 checkpoint,需强一致 + 高可用etcd
消息存储 Log Broker持久化流式写入、解耦读写、支持回放(日志即数据)Pulsar / Kafka(分布式);RocksDB(单机)
对象存储 Object日志快照、向量/标量索引文件、中间结果MinIO / S3 / GCS

③数据模型:这些概念必须分清

Milvus 概念类比关系型库说明
Collection表(Table)一组实体的逻辑集合,含向量字段与标量字段
Entity行(Row)一条数据 = 若干 field 组成
Field列(Column)可以是向量,也可以是标量(int/float/string/bool/JSON)
Primary Key主键唯一标识实体;可自定义,否则自动生成
Partition分区物理切分,减少读取范围(按业务维度划分)
Sharding分片默认 2 个,按主键哈希把写入打散到多节点并行
Segment数据文件数据组织与调度的基本单位(见下)
Channel (P/V)日志主题PChannel 物理、VChannel 逻辑,记录增删改日志

Segment:数据调度的最小单元

Growing Segment 活跃段 · 增量写入 常在内存 · 多未建索引 Sealed Segment 密封段 · 不可变 已落对象存储 Indexed Segment 建好索引 QueryNode 加载检索 达到阈值 → DataCoord 封口 → IndexCoord 触发建索引 → QueryCoord 分配到 QueryNode

④实现原理:为什么这么设计

日志即数据

所有变更先写日志 broker,再异步快照到对象存储。节点宕机靠「回放日志」恢复增量,读写彻底解耦。

存储计算分离

计算节点无状态、可随 K8s 弹性伸缩;数据在对象存储,扩容不必迁移数据。

Knowhere 引擎

统一的向量执行引擎,封装 FAISS/Annoy/HNSW 与量化算法,屏蔽底层差异,并原生支持 SIMD。

SIMD 加速

距离计算(L2/IP)用 SSE/AVX2/AVX512 单指令多数据并行,是向量检索性能的关键。

谓词下推

混合查询时先把标量过滤(Bitset)应用到各段,再在候选集上做向量检索,大幅减少计算量。

一致性 / Time Travel

RootCoord 的 TSO 提供全局有序时间戳,支持强一致到最终一致多档,以及按时间戳回看历史。

⑤核心流程一:写入(Insert)

Client Proxy Log Broker (Pulsar/Kafka) DataNode 落盘 对象存储 (S3/MinIO) ① 写 WAL → ② DataNode 打包快照 → ③ 达到阈值封口为 Sealed Segment → ④ IndexNode 异步建索引
  1. Client 发 Insert,Proxy 校验并写入 Log Broker(WAL,保证持久)。
  2. DataNode 订阅日志,把数据打包成 日志快照 持久化到对象存储。
  3. 增量数据以 Growing Segment 形式存在于 QueryNode 内存;达阈值后 DataCoord 将其封口(Seal)。
  4. IndexCoord 调度 IndexNode 对 Sealed Segment 异步建索引,索引文件写回对象存储。

⑥核心流程二:查询(Search)

Client Proxy QueryNode QueryNode QueryNode ① 广播:Proxy 把查询同时发给所有 QueryNode(MPP 并行) ② 各节点:先标量过滤(Bitset) → 再在本地段做向量检索 → 返回局部 TopK ③ 归并:Proxy 收齐各节点结果,全局排序后返回最终 TopK 注:未建索引的 Growing Segment 走「暴力全扫」兜底,建索引后才走 ANN

查询采用 大规模并行处理(MPP):Proxy 不自己算,而是把请求广播给所有相关 QueryNode,各自算完局部 TopK 再归并。这就是为什么节点越多、检索越快。

⑦核心流程三:建索引(Index Build)

索引不是写入时同步建的,而是对 Sealed Segment 异步、按需构建——这正是 Milvus 能把「写入」和「检索性能」解耦的关键。
  1. DataCoord 封口段后,IndexCoord 生成索引任务下发给 IndexNode。
  2. IndexNode 从对象存储把段数据载入内存(涉及大量 K-means / 图遍历,吃算力)。
  3. 构建完成后,索引文件(质心 / 编码 / 图边 + 内部 ID,不是完整向量)序列化写回对象存储。
  4. QueryCoord 通知各 QueryNode 加载新索引;此后该段检索走 ANN,未就绪前走暴力。
为控制资源,IndexNode 可 serverless 化(按需拉起、用完即释放);索引类型按向量字段指定(一个向量字段一种索引),切换索引时旧索引自动删除。
关于 Milvus 支持哪些具体的向量索引算法(IVF / HNSW / DiskANN …)、原理与选型,请见同目录的 《向量索引》 文档。