Milvus 完整执行流程:写入、检索两大阶段拆解
目录
Step4 DataNode 内存缓冲 MemTable 与活跃段(Growing Segment)
Step5 段 Seal 固化机制,生成密封段 Sealed Segment
Step2 QueryCoord 任务拆分、负载均衡、副本调度
一、前置知识
Milvus面向的是做 RAG 知识库、图文相似检索、大模型向量存储等的开发场景,而使用时大部分人只知道调用SDK 的 insert、search 接口,完全不懂底层一条向量从入库到检索返回结果完整发生了什么
要完全理清写入和检索的执行流程,我们要先了解:
- Client:业务端 SDK,发起增删查改请求
- Proxy:统一网关入口,负责参数校验、路由分发、协议解析、权限控制、读写请求限流
- 三大协调器 Coordinator(集群元数据调度核心,无状态)
- RootCoord:全局元数据管理,集合、分区、Schema、用户权限、索引元数据全部存入 ETCD;负责 DDL 操作(create_collection/drop_collection
- DataCoord:管控写入链路、段固化触发、Compaction 小段合并调度、索引构建任务分发、段生命周期管
- QueryCoord:管控查询节点负载均衡、拆分分发检索子任务、段加载 / 卸载调度、副本管理
- 两类工作节点 Worker(有状态,负责实际数据操作)
- DataNode:处理写入内存缓存、段落盘持久化、合并段数据、构建向量索引、执行删除数据标记落地
- QueryNode:内存加载向量段、执行标量过滤、向量相似度计算、本地结果排序、管理段内存缓存淘汰
- 三层存储系统(存储计算分离核心设计)
- ETCD:强一致元数据存储,存所有集合、段、索引、分区元信息,高可用集群部署
- Pulsar/Kafka:WAL 预写日志,写入宕机容错、数据回放恢复
- MinIO / 本地磁盘 / S3:持久化原始向量文件、索引二进制文件、标量字段文件、删除位图文件
二、向量数据写入 Insert 完整流程
写入阶段独立 Mermaid 流程图
步骤详解
Step1 客户端请求与 Proxy 多层校验
- 业务侧必须推荐批量插入,单条 insert 会产生海量微型 Segment,直接摧毁查询性能;
- Proxy 四层校验逻辑:
- 权限校验:当前账号是否拥有该集合写入权限;
- Schema 校验:向量维度、字段数据类型、主键是否重复、是否开启自增主键冲突;
- 参数范围校验:批量插入条数上限、向量数值合法性;
- 集合状态校验:集合是否存在、是否处于加载 / 删除中不可写状态;
补充:Proxy 无状态,可水平无限扩容,所有请求统一接入 Proxy 做网关分流
Step2 WAL 预写日志落地,写入容错核心机制
- 核心规则:日志落盘成功,Proxy 才会下发数据至 DataNode,两步写入不可逆;
- WAL 作用:故障恢复、主从副本同步。如果 DataNode 宕机,重启后会消费 Pulsar 未消费日志,回放恢复内存未固化数据,零数据丢失;
补充:WAL 是消息队列持久化,性能损耗极低,是 Milvus 保证写入 ACID 中持久性 (D) 的核心手段
Step3 路由分发与分区分片逻辑
- RootCoord 维护集合分区路由表,写入数据会按分区哈希路由分发到对应 DataNode,分区是 Milvus 横向数据拆分第一层隔离单元;
补充:分区仅做数据隔离,不参与检索并行;同一分区内所有 Segment 由同一批 DataNode 处理写入;分区过多会增加元数据管理压力
Step4 DataNode 内存缓冲 MemTable 与活跃段(Growing Segment)
- MemTable 是 DataNode 内存缓冲区,对应活跃段 Growing Segment;
- 活跃段特性:可追加写入、只读不持久化磁盘、无法构建向量索引;检索活跃段只能暴力全量扫描,海量数据场景查询延迟极高;
- 内存阈值配置:memtable.max.size,到达阈值自动触发固化;未到阈值会常驻内存,直到定时 flush 或手动 flush
Step5 段 Seal 固化机制,生成密封段 Sealed Segment
三大固化触发条件
- 内存阈值触发:MemTable 数据量达到配置上限;
- 定时固化:后台定时任务,超过指定时长自动固化内存数据;
- 手动触发:业务调用
collection.flush()强制全内存段固化;密封段核心特性
- 只读、不可追加新向量;
- 完整持久化至对象存储,包含向量文件、标量文件、主键索引、删除位图;
- 支持异步构建向量索引,检索时走索引加速;
补充:Segment 是 Milvus 最小存储、索引、检索单元,所有调度、加载、合并、建索引都以 Segment 为单位
Step6 DataCoord 更新 ETCD 元数据
- 段文件落盘完成后,DataCoord 立刻在 ETCD 写入新 Segment 完整元信息:段 ID、所属分区、向量数量、存储路径、索引状态、创建时间、删除标记位图状态;
补充:ETCD 元数据全局唯一,所有 Coord、Node 实时同步元数据,集群任意节点均可感知新增段
Step7 Compaction 段合并
- 痛点:频繁少量批量插入会生成成千上百个微型 Sealed 段;检索时 QueryNode 需要并行加载、遍历所有小段,IO、计算量成倍上涨,查询延迟暴涨;
- 合并流程:
- DataCoord 后台定时扫描所有小段,筛选向量总量少的 Segment,下发合并任务给 DataNode;
- DataNode 读取所有小段原始数据,去重、剔除已删除向量,生成单个大容量新 Segment;
- 新段落盘后 ETCD 标记旧段为待删除,后台延迟清理磁盘旧文件;
- 细分两种合并类型:
- Minor Compaction:合并少量微型段,轻量后台任务,资源占用低;
- Major Compaction:大规模合并,同时清理已删除向量,释放存储空间,CPU、IO 开销更高;
- 手动优化:线上可定时调用 compact 接口主动触发合并,避免自动合并高峰抢占业务资源。
Step8 异步离线构建向量索引
- 核心规则:索引构建完全异步、离线、不阻塞写入链路,写入和建索引资源隔离;
- 执行逻辑:
- DataCoord 轮询 ETCD,检测到无索引的 Sealed 段,分配空闲 DataNode 执行建索引;
- DataNode 从 MinIO 读取原始向量,根据指定索引类型(HNSW/IVF_FLAT/IVF_SQ8 等)计算索引结构,索引文件独立落盘;
- 完成后更新 ETCD 标记该段索引就绪;
补充:
- Growing 活跃段永远无法构建索引;
- 索引文件和原始向量文件分开存储,可单独删除、重建索引,无需重写原始向量;
- 重建索引仅影响对应 Segment,不会中断集合读写
三、向量相似检索 Search 完整流程
检索阶段独立 Mermaid 流程图
步骤详解
Step1 Proxy 校验与全局元数据拉取
- Proxy 校验范围:查询向量维度、topk 数值上限、过滤字段是否存在、过滤表达式语法合法性、集合读写状态;
- 元数据拉取目的:一次性获取集合所有分区、所有 Segment、段索引状态、段向量数量,区分活跃段 / 密封段,提前预判本次查询是否会触发全量扫描;
补充:大集合元数据量大时,Proxy 会缓存 ETCD 元数据,减少重复查询 ETCD 压力
Step2 QueryCoord 任务拆分、负载均衡、副本调度
- QueryCoord 核心三大职责:任务拆分、节点负载均衡、Segment 副本调度;
- 并行拆分逻辑:每个 Segment 分配独立检索子任务,分发到加载该段的 QueryNode,实现多节点并行计算;
补充(高频考点):
- Milvus 支持多副本,同一 Segment 可加载至多个 QueryNode;
- 检索请求可分发至任意副本节点,实现查询高可用、查询负载分流;
- 单副本节点宕机,检索自动切换其他副本
Step3 QueryNode 段内存加载、缓存淘汰机制
- 段加载完整文件:原始向量文件、索引文件、标量字段文件、删除位图文件;密封段优先加载索引文件,减少向量读取开销;
- 热点段缓存机制:QueryNode 内置 LRU 内存淘汰策略;高频访问热点段长期驻留内存;长期未访问冷段自动卸载释放内存,避免 OOM;
补充:内存不足时频繁卸载 / 加载段,会产生大量 MinIO 磁盘 IO,查询延迟飙升,生产环境需要预留充足 QueryNode 内存
Step4 两层前置过滤
(性能优化核心知识点)
Milvus 检索先过滤、后计算向量相似度,极大减少向量计算开销,分为两层过滤:
- 标量 Where 条件过滤
- 解析用户传入过滤表达式(age>18、category="数码"),遍历标量字段筛选符合条件主键;
- 优化点:高频过滤字段创建标量索引(倒排索引),过滤速度提升数十倍;无标量索引会全段遍历标量字段;
- 删除位图 DeleteBitmap 过滤
- Milvus 删除为软删除,不会立刻物理删除向量;每个 Segment 维护一张位图,标记哪些主键已被删除;
- 相似度计算完成后,直接剔除位图标记删除的数据,不会返回已删除向量;
- 只有 Major Compaction 大规模合并时,才会物理剔除已删除向量,释放磁盘与内存空间。
Step5 双分支检索逻辑
(ANN 近似检索 VS 暴力全量扫描)
分支 1:Sealed 密封段
(索引就绪,推荐主流场景)
- 采用 ANN 近似最近邻算法(HNSW/IVF 系列),牺牲极小精度,换取百万级向量毫秒检索;
- 支持检索参数调优:HNSW 的 ef、IVF 的 nprobe,平衡查询速度与召回精度;
分支 2:Growing 活跃段
(无索引,性能坑点)
- 无索引结构,只能暴力线性扫描所有未过滤向量,逐个计算余弦 / 内积 / 欧式距离;
- 线上重大性能问题根源:大批量数据未 flush 固化,活跃段向量量巨大,每次查询触发全量扫描,延迟数十倍上涨;
核心优化知识点:生产环境定时 flush,保证绝大多数数据进入密封段并构建索引
Step6 本地局部 TopK 裁剪
- 每个 QueryNode 仅对自己负责的 Segment 做排序,只返回本段相似度最高的局部 TopK 结果,而非全部向量距离数据;
补充:大幅降低跨节点网络传输的数据量,亿级向量分布式查询下,网络开销减少 90% 以上
Step7 QueryCoord 全局结果合并、重排序
- 汇总所有 QueryNode 返回的局部候选结果,统一按相似度分数全局排序;
- 裁剪出用户指定的最终 TopK 条数,去除重复主键(跨 Segment 重复写入场景);
补充:如果开启分页查询(offset),会放大候选结果数量,查询延迟显著上升,Milvus 不支持超大 offset 分页,推荐游标分页
Step8 Proxy 格式化返回结果
Proxy 统一封装相似度分数、主键、标量字段、距离值,转换为 SDK 统一格式返回客户端;同时记录查询埋点指标(查询耗时、扫描段数量、扫描向量总数),用于监控告警。
检索额外补充知识点
- 读写完全隔离:QueryNode 只做检索计算,不参与任何写入、建索引任务,读写并发互不抢占 CPU、内存资源;
- 存储计算分离优势:向量数据全部外置存储,新增 QueryNode 节点无需迁移数据,仅按需加载 Segment 即可横向扩容查询能力;
- 并发隔离:多集合、多分区检索任务在 QueryNode 内部线程池隔离,单集合慢查询不会阻塞其他集合检索;
- 过滤优先级:标量过滤 > 删除过滤 > 向量相似度计算,是 Milvus 查询性能优化第一优先级
四、写入 & 检索全流程核心综合知识点(面试可看)
1. Segment 分段核心体系
- Segment 分为两类:Growing 活跃段(内存可写无索引)、Sealed 密封段(磁盘只读支持索引);
- Segment 是 Milvus 最小调度单元:固化、合并、建索引、加载、检索全部以 Segment 为单位;
- 线上性能 80% 问题根源:大量微型 Segment、超大容量活跃段
2. 三大协调器分工本质区别
- RootCoord:管全局元数据、集合 / 分区 DDL;
- DataCoord:管写入链路、段生命周期、索引构建;
- QueryCoord:管查询负载、段加载、检索任务分发; 三者完全解耦,独立扩容,互不影响
3. 容错与数据一致性完整机制
- 写入容错:WAL 预写日志保证宕机不丢数据;
- 查询容错:Segment 多副本,单 QueryNode 宕机自动切换副本;
- 删除一致性:DeleteBitmap 软删除,后台合并清理,保证读写期间数据可见性统一;
- 元数据一致性:ETCD 强一致存储,集群所有节点实时同步元数据
4. 线上性能调优核心思路
写入调优
(对应写入流程)
- 批量插入,单次条数控制在 1000~10000;
- 定时手动 flush,减少活跃段数据量;
- 合理配置 memtable 内存阈值,平衡固化频率;
- 监控 Segment 数量,自动 / 手动触发 Compaction 合并小段;
- 密封段写入完成后及时构建索引
查询调优
(对应检索流程)
- 减少活跃段数据,避免全量暴力扫描;
- 高频过滤字段创建标量索引;
- 合理设置索引参数(ef/nprobe)平衡速度与召回;
- 预留充足 QueryNode 内存,减少冷热段频繁卸载加载;
- 避免超大 offset 分页查询,改用游标遍历
5. 架构设计核心优势总结
- 读写分离:DataNode/QueryNode 职责完全拆分,高并发读写互不干扰;
- 存储计算分离:向量数据外置对象存储,集群弹性扩缩容无数据迁移成本;
- 全链路异步后台任务:固化、合并、建索引离线执行,不阻塞业务读写接口;
- 分布式并行计算:写入按分区拆分,检索按 Segment 多节点并行,天然支撑亿级向量海量场景;
- 分层内存优化:写入侧内存缓冲提升吞吐,查询侧 LRU 热点缓存降低磁盘 IO
更多推荐






所有评论(0)