向量数据库

Milvus:云原生存算分离架构

进阶系统架构约 30 分钟kp-019

前置知识

一句话定义

Milvus 是云原生分布式向量库的代表:存算分离 + 日志即数据——所有写入先落消息队列(Pulsar/Kafka)作为唯一事实源,数据节点消费日志落对象存储(S3/MinIO),查询节点按需加载段(segment)建索引读数,各角色独立弹性伸缩。

为什么重要

读 Milvus 架构等于读一遍"向量数据库如何长成分布式系统"的标准答案:growing/sealed 段的双路径读、一致性级别与可见性、索引构建异步化——这些机制在几乎所有现代向量库中以变体出现。大规模(十亿级、多租户、K8s 环境)选型绕不开它,也绕不开它带来的组件复杂度。

前置知识

kp-018(专用分布式谱系的定位);分布式系统基本词汇(角色、消息队列、对象存储)。

核心概念

原理与机制

一条写入的生命周期:SDK → proxy → 按主键哈希路由到某 shard → 追加进消息队列 → data node 消费写入 growing segment(内存,查询侧暴力扫描立即可见)→ segment 达到阈值后 sealed → index node 异步构建 IVF/HNSW/DiskANN/GPU 索引 → 落对象存储 → query node 加载 sealed segment 切换读路径,growing 段释放。

一次查询的执行:proxy 按一致性级别计算可用快照 → 通知相关 query node → 各 segment 本地执行(sealed 走索引 + growing 暴力 + tombstone 过滤)→ 归并 top-k 返回。

这套设计的三个直接后果:

  1. 写入吞吐高且平稳(追加日志),但可见性有延迟——强一致读要付出协调代价;
  2. 索引构建不阻塞写入(异步流水线),但意味着"建索引中"的数据走慢路径;
  3. 组件多(协调器、队列、对象存储、etcd)——单机版替你打包,分布式版要求 K8s 运维能力。

公式或模型

本节不适用:架构剖析篇;容量与副本计算见 kp-026/029。

图示

 SDK ─► proxy ─► [消息队列: log as data]◄───唯一事实源
                    │ 消费
        data node ──┴─► growing segment(内存,暴力扫)
                            │ 满则 seal
        index node ──► sealed segment + ANN 索引 ─► 对象存储
                            │ 加载
        query node ──► 索引查询 + tombstone 过滤 ─► 归并 ─► proxy ─► SDK
 (root/data/query/index coordinator 协调元数据与负载, 图中省略)

实例或案例

RAG 知识平台(8 亿 chunk、日均千万级更新、需要按租户与权限过滤):选 Milvus Distributed,collection 按租户分区,HNSW 索引 + scalar 过滤;写入侧 p99 稳定因为日志追加;查询侧用 Bounded 一致性(容忍秒级可见延迟换吞吐)。对照组:同需求用单机 Qdrant 需要自行拆分与复制,运维脚本化程度高——规模与团队 K8s 能力是选 Milvus 的决定性输入。

直观类比

Milvus 像"中央厨房体系":订单先统一记账(消息队列),切菜组(data node)实时处理小批次,入库组(index node)把大批食材整理上架(建索引放冷库),出菜口(query node)从冷库与台面同时取料。分工带来吞吐,也带来"部门协调"的复杂度(coordinator 与运维)。

常见误区

  1. "写入成功 = 立即可查"——默认可见性有延迟;强一致场景必须显式选 Strong 一致性并接受代价,或等待 flush(与 kp-022 的可见性语义联动)。
  2. "Standalone 与 Distributed 只是参数差别"——Distributed 引入消息队列与对象存储依赖、副本与再平衡机制,运维等级完全不同;从小规模起步应从 Lite/Standalone 开始。
  3. "Milvus 慢"——脱离 segment 状态谈延迟无意义:查询落在大量 growing 段(暴力扫)时自然慢,解决方案是控制 flush/compact 节奏而不是换引擎。

自测题

  1. "日志即数据"解决了什么核心矛盾?
  2. 答:写入持久性与查询服务的解耦——写入只追加日志(快且稳),落盘与索引作为异步下游,故障恢复从日志重放,避免写路径直接依赖复杂存储结构。

  3. growing 与 sealed 段的读路径差别?
  4. 答:growing 段在内存无索引,暴力扫描 + tombstone 过滤保证实时可见;sealed 段有 ANN 索引走高性能路径,两者结果归并。

  5. 为什么大团队选 Milvus Distributed 而不是多个 Standalone 实例?
  6. 答:原生分片/副本/再平衡/多租户配额由系统保证,避免自研路由、复制与故障转移——自研这些的隐性成本通常高于分布式版的运维成本。

与其他知识点的关系

kp-022 把本篇的可见性与段机制展开为通用写删语义;kp-029 的分片副本在本篇架构上落地;kp-030 的运维清单大量条目源于 Milvus 类架构的典型故障。

延伸阅读

Wang et al., "Milvus: A Purpose-Built Vector Data Management System"(SIGMOD 2021)——本篇架构的原始设计文档,云原生向量库的代表性论述。

相关知识点