02 Milvus-Milvus整体架构

「milvus-course-ai.zip」
链接:https://pan.quark.cn/s/00f3d411bb6d

github:https://github.com/yuanmomoya/milvus

学习目标

学完本章后,你应该能够:

  • 说清 Proxy、Coord、Node、etcd、MinIO、Pulsar/Rocksmq 的职责。
  • 画出 Milvus 写入流、查询流和索引构建流。
  • 理解 Segment 生命周期、Flush、Compaction、WAL。
  • 判断一个生产问题大概率发生在哪个组件。
  • 区分单机 Standalone 和分布式 Cluster 的架构差异。

理论知识:形象化理解

Milvus 的架构可以想象成一个大型物流中心。Proxy 是前台接待,负责接收客户订单;Coord 系列像调度室,决定货物放在哪里、由谁搬运、什么时候合并;Node 系列像具体操作工位,真正执行写入、查询和建索引;etcd 是调度室墙上的总账本,MinIO/S3 是后方仓库,消息队列则是传送带和流水号系统。

写入一条向量,不是把数据直接塞进某个单独文件就结束。它会先进入 WAL,像订单先贴上可追溯的流水号;DataNode 再消费消息、形成 growing segment;Flush 后数据落到对象存储,Segment 被封存;IndexNode 再把它加工成适合快速搜索的索引。查询时,Proxy 会把请求拆给多个 QueryNode,拿到局部 TopK 后再归并成全局 TopK。

所以排查 Milvus 问题要像看物流链路一样定位:是前台接单慢、传送带堵了、仓库 IO 慢、调度表错了,还是搜索工位内存不够。架构图不是背组件名,而是建立"现象到组件"的映射。

总体架构

Milvus 采用计算存储分离和多组件协同架构。Proxy 接入请求,Coord 系列负责元数据和调度,Node 系列负责具体执行,etcd 保存元数据,对象存储保存 Binlog/Index 文件,消息队列承载写入日志和事件流。
#mermaid-svg-L9ZhbeDocIxMb2AO{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-L9ZhbeDocIxMb2AO .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-L9ZhbeDocIxMb2AO .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-L9ZhbeDocIxMb2AO .error-icon{fill:#552222;}#mermaid-svg-L9ZhbeDocIxMb2AO .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-L9ZhbeDocIxMb2AO .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-L9ZhbeDocIxMb2AO .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-L9ZhbeDocIxMb2AO .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-L9ZhbeDocIxMb2AO .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-L9ZhbeDocIxMb2AO .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-L9ZhbeDocIxMb2AO .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-L9ZhbeDocIxMb2AO .marker{fill:#333333;stroke:#333333;}#mermaid-svg-L9ZhbeDocIxMb2AO .marker.cross{stroke:#333333;}#mermaid-svg-L9ZhbeDocIxMb2AO svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-L9ZhbeDocIxMb2AO p{margin:0;}#mermaid-svg-L9ZhbeDocIxMb2AO .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-L9ZhbeDocIxMb2AO .cluster-label text{fill:#333;}#mermaid-svg-L9ZhbeDocIxMb2AO .cluster-label span{color:#333;}#mermaid-svg-L9ZhbeDocIxMb2AO .cluster-label span p{background-color:transparent;}#mermaid-svg-L9ZhbeDocIxMb2AO .label text,#mermaid-svg-L9ZhbeDocIxMb2AO span{fill:#333;color:#333;}#mermaid-svg-L9ZhbeDocIxMb2AO .node rect,#mermaid-svg-L9ZhbeDocIxMb2AO .node circle,#mermaid-svg-L9ZhbeDocIxMb2AO .node ellipse,#mermaid-svg-L9ZhbeDocIxMb2AO .node polygon,#mermaid-svg-L9ZhbeDocIxMb2AO .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-L9ZhbeDocIxMb2AO .rough-node .label text,#mermaid-svg-L9ZhbeDocIxMb2AO .node .label text,#mermaid-svg-L9ZhbeDocIxMb2AO .image-shape .label,#mermaid-svg-L9ZhbeDocIxMb2AO .icon-shape .label{text-anchor:middle;}#mermaid-svg-L9ZhbeDocIxMb2AO .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-L9ZhbeDocIxMb2AO .rough-node .label,#mermaid-svg-L9ZhbeDocIxMb2AO .node .label,#mermaid-svg-L9ZhbeDocIxMb2AO .image-shape .label,#mermaid-svg-L9ZhbeDocIxMb2AO .icon-shape .label{text-align:center;}#mermaid-svg-L9ZhbeDocIxMb2AO .node.clickable{cursor:pointer;}#mermaid-svg-L9ZhbeDocIxMb2AO .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-L9ZhbeDocIxMb2AO .arrowheadPath{fill:#333333;}#mermaid-svg-L9ZhbeDocIxMb2AO .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-L9ZhbeDocIxMb2AO .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-L9ZhbeDocIxMb2AO .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-L9ZhbeDocIxMb2AO .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-L9ZhbeDocIxMb2AO .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-L9ZhbeDocIxMb2AO .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-L9ZhbeDocIxMb2AO .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-L9ZhbeDocIxMb2AO .cluster text{fill:#333;}#mermaid-svg-L9ZhbeDocIxMb2AO .cluster span{color:#333;}#mermaid-svg-L9ZhbeDocIxMb2AO div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-L9ZhbeDocIxMb2AO .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-L9ZhbeDocIxMb2AO rect.text{fill:none;stroke-width:0;}#mermaid-svg-L9ZhbeDocIxMb2AO .icon-shape,#mermaid-svg-L9ZhbeDocIxMb2AO .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-L9ZhbeDocIxMb2AO .icon-shape p,#mermaid-svg-L9ZhbeDocIxMb2AO .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-L9ZhbeDocIxMb2AO .icon-shape .label rect,#mermaid-svg-L9ZhbeDocIxMb2AO .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-L9ZhbeDocIxMb2AO .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-L9ZhbeDocIxMb2AO .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-L9ZhbeDocIxMb2AO :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} SDK / REST / 应用服务
Proxy
RootCoord
QueryCoord
DataCoord
IndexCoord
DataNode
QueryNode
IndexNode
etcd 元数据
Pulsar/Rocksmq 消息流
MinIO/S3 对象存储

组件职责

组件 职责 生产关注点
Proxy 接收客户端请求、鉴权、路由、参数校验 QPS、连接数、请求错误率
RootCoord 管理数据库、Collection、字段、时间戳 元数据一致性、DDL 延迟
DataCoord 管理 Segment、Flush、Compaction Segment 数量、Compaction 积压
DataNode 消费写入日志,生成 Binlog 写入吞吐、Flush 延迟
QueryCoord 调度 QueryNode,管理 load/release 加载耗时、副本分配
QueryNode 加载 Segment,执行搜索和查询 内存、搜索延迟、慢查询
IndexCoord 调度索引构建任务 索引任务积压
IndexNode 构建向量/标量索引 CPU/GPU、构建耗时
etcd 元数据和服务发现 备份、延迟、磁盘空间
MinIO/S3 Binlog、DeltaLog、Index 文件 容量、吞吐、可靠性
Pulsar/Rocksmq WAL 和消息流 消费延迟、积压、持久化

写入流程

QueryNode DataCoord MinIO/S3 DataNode WAL/MQ Proxy 应用 QueryNode DataCoord MinIO/S3 DataNode WAL/MQ Proxy 应用 #mermaid-svg-jriKwGzkZyABmdxR{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-jriKwGzkZyABmdxR .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-jriKwGzkZyABmdxR .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-jriKwGzkZyABmdxR .error-icon{fill:#552222;}#mermaid-svg-jriKwGzkZyABmdxR .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-jriKwGzkZyABmdxR .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-jriKwGzkZyABmdxR .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-jriKwGzkZyABmdxR .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-jriKwGzkZyABmdxR .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-jriKwGzkZyABmdxR .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-jriKwGzkZyABmdxR .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-jriKwGzkZyABmdxR .marker{fill:#333333;stroke:#333333;}#mermaid-svg-jriKwGzkZyABmdxR .marker.cross{stroke:#333333;}#mermaid-svg-jriKwGzkZyABmdxR svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-jriKwGzkZyABmdxR p{margin:0;}#mermaid-svg-jriKwGzkZyABmdxR .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-jriKwGzkZyABmdxR text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-jriKwGzkZyABmdxR .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-jriKwGzkZyABmdxR .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-jriKwGzkZyABmdxR .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-jriKwGzkZyABmdxR .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-jriKwGzkZyABmdxR #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-jriKwGzkZyABmdxR .sequenceNumber{fill:white;}#mermaid-svg-jriKwGzkZyABmdxR #sequencenumber{fill:#333;}#mermaid-svg-jriKwGzkZyABmdxR #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-jriKwGzkZyABmdxR .messageText{fill:#333;stroke:none;}#mermaid-svg-jriKwGzkZyABmdxR .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-jriKwGzkZyABmdxR .labelText,#mermaid-svg-jriKwGzkZyABmdxR .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-jriKwGzkZyABmdxR .loopText,#mermaid-svg-jriKwGzkZyABmdxR .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-jriKwGzkZyABmdxR .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-jriKwGzkZyABmdxR .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-jriKwGzkZyABmdxR .noteText,#mermaid-svg-jriKwGzkZyABmdxR .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-jriKwGzkZyABmdxR .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-jriKwGzkZyABmdxR .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-jriKwGzkZyABmdxR .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-jriKwGzkZyABmdxR .actorPopupMenu{position:absolute;}#mermaid-svg-jriKwGzkZyABmdxR .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-jriKwGzkZyABmdxR .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-jriKwGzkZyABmdxR .actor-man circle,#mermaid-svg-jriKwGzkZyABmdxR line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-jriKwGzkZyABmdxR :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} insert/upsert 写入 WAL ack 写入成功 消费写入消息 形成 growing segment flush binlog 上报 sealed segment 通知加载新 segment

写入成功通常意味着数据进入 WAL,并不等于索引已经构建完成。新写入数据可能先在 growing segment 中被暴力搜索,Flush 后成为 sealed segment,再由 IndexNode 构建索引。

查询流程

QueryNode B QueryNode A QueryCoord Proxy 应用 QueryNode B QueryNode A QueryCoord Proxy 应用 #mermaid-svg-GObsI8DvbTA5JY1E{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-GObsI8DvbTA5JY1E .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-GObsI8DvbTA5JY1E .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-GObsI8DvbTA5JY1E .error-icon{fill:#552222;}#mermaid-svg-GObsI8DvbTA5JY1E .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-GObsI8DvbTA5JY1E .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-GObsI8DvbTA5JY1E .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-GObsI8DvbTA5JY1E .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-GObsI8DvbTA5JY1E .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-GObsI8DvbTA5JY1E .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-GObsI8DvbTA5JY1E .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-GObsI8DvbTA5JY1E .marker{fill:#333333;stroke:#333333;}#mermaid-svg-GObsI8DvbTA5JY1E .marker.cross{stroke:#333333;}#mermaid-svg-GObsI8DvbTA5JY1E svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-GObsI8DvbTA5JY1E p{margin:0;}#mermaid-svg-GObsI8DvbTA5JY1E .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-GObsI8DvbTA5JY1E text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-GObsI8DvbTA5JY1E .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-GObsI8DvbTA5JY1E .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-GObsI8DvbTA5JY1E .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-GObsI8DvbTA5JY1E .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-GObsI8DvbTA5JY1E #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-GObsI8DvbTA5JY1E .sequenceNumber{fill:white;}#mermaid-svg-GObsI8DvbTA5JY1E #sequencenumber{fill:#333;}#mermaid-svg-GObsI8DvbTA5JY1E #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-GObsI8DvbTA5JY1E .messageText{fill:#333;stroke:none;}#mermaid-svg-GObsI8DvbTA5JY1E .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-GObsI8DvbTA5JY1E .labelText,#mermaid-svg-GObsI8DvbTA5JY1E .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-GObsI8DvbTA5JY1E .loopText,#mermaid-svg-GObsI8DvbTA5JY1E .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-GObsI8DvbTA5JY1E .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-GObsI8DvbTA5JY1E .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-GObsI8DvbTA5JY1E .noteText,#mermaid-svg-GObsI8DvbTA5JY1E .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-GObsI8DvbTA5JY1E .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-GObsI8DvbTA5JY1E .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-GObsI8DvbTA5JY1E .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-GObsI8DvbTA5JY1E .actorPopupMenu{position:absolute;}#mermaid-svg-GObsI8DvbTA5JY1E .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-GObsI8DvbTA5JY1E .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-GObsI8DvbTA5JY1E .actor-man circle,#mermaid-svg-GObsI8DvbTA5JY1E line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-GObsI8DvbTA5JY1E :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} search(collection, vector, filter) 获取 shard/segment 分布 搜索部分 Segment 搜索部分 Segment 局部 TopK 局部 TopK 归并、排序、回填字段 全局 TopK

查询性能由多个因素共同决定:Collection 是否已 load,Segment 是否过碎,索引是否构建完成,过滤条件能否减少搜索范围,输出字段是否过大。

Segment 生命周期

#mermaid-svg-bZvCVOxmXvZITNKC{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-bZvCVOxmXvZITNKC .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-bZvCVOxmXvZITNKC .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-bZvCVOxmXvZITNKC .error-icon{fill:#552222;}#mermaid-svg-bZvCVOxmXvZITNKC .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-bZvCVOxmXvZITNKC .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-bZvCVOxmXvZITNKC .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-bZvCVOxmXvZITNKC .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-bZvCVOxmXvZITNKC .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-bZvCVOxmXvZITNKC .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-bZvCVOxmXvZITNKC .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-bZvCVOxmXvZITNKC .marker{fill:#333333;stroke:#333333;}#mermaid-svg-bZvCVOxmXvZITNKC .marker.cross{stroke:#333333;}#mermaid-svg-bZvCVOxmXvZITNKC svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-bZvCVOxmXvZITNKC p{margin:0;}#mermaid-svg-bZvCVOxmXvZITNKC defs #statediagram-barbEnd{fill:#333333;stroke:#333333;}#mermaid-svg-bZvCVOxmXvZITNKC g.stateGroup text{fill:#9370DB;stroke:none;font-size:10px;}#mermaid-svg-bZvCVOxmXvZITNKC g.stateGroup text{fill:#333;stroke:none;font-size:10px;}#mermaid-svg-bZvCVOxmXvZITNKC g.stateGroup .state-title{font-weight:bolder;fill:#131300;}#mermaid-svg-bZvCVOxmXvZITNKC g.stateGroup rect{fill:#ECECFF;stroke:#9370DB;}#mermaid-svg-bZvCVOxmXvZITNKC g.stateGroup line{stroke:#333333;stroke-width:1;}#mermaid-svg-bZvCVOxmXvZITNKC .transition{stroke:#333333;stroke-width:1;fill:none;}#mermaid-svg-bZvCVOxmXvZITNKC .stateGroup .composit{fill:white;border-bottom:1px;}#mermaid-svg-bZvCVOxmXvZITNKC .stateGroup .alt-composit{fill:#e0e0e0;border-bottom:1px;}#mermaid-svg-bZvCVOxmXvZITNKC .state-note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-bZvCVOxmXvZITNKC .state-note text{fill:black;stroke:none;font-size:10px;}#mermaid-svg-bZvCVOxmXvZITNKC .stateLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5;}#mermaid-svg-bZvCVOxmXvZITNKC .edgeLabel .label rect{fill:#ECECFF;opacity:0.5;}#mermaid-svg-bZvCVOxmXvZITNKC .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-bZvCVOxmXvZITNKC .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-bZvCVOxmXvZITNKC .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-bZvCVOxmXvZITNKC .edgeLabel .label text{fill:#333;}#mermaid-svg-bZvCVOxmXvZITNKC .label div .edgeLabel{color:#333;}#mermaid-svg-bZvCVOxmXvZITNKC .stateLabel text{fill:#131300;font-size:10px;font-weight:bold;}#mermaid-svg-bZvCVOxmXvZITNKC .node circle.state-start{fill:#333333;stroke:#333333;}#mermaid-svg-bZvCVOxmXvZITNKC .node .fork-join{fill:#333333;stroke:#333333;}#mermaid-svg-bZvCVOxmXvZITNKC .node circle.state-end{fill:#9370DB;stroke:white;stroke-width:1.5;}#mermaid-svg-bZvCVOxmXvZITNKC .end-state-inner{fill:white;stroke-width:1.5;}#mermaid-svg-bZvCVOxmXvZITNKC .node rect{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-bZvCVOxmXvZITNKC .node polygon{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-bZvCVOxmXvZITNKC #statediagram-barbEnd{fill:#333333;}#mermaid-svg-bZvCVOxmXvZITNKC .statediagram-cluster rect{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-bZvCVOxmXvZITNKC .cluster-label,#mermaid-svg-bZvCVOxmXvZITNKC .nodeLabel{color:#131300;}#mermaid-svg-bZvCVOxmXvZITNKC .statediagram-cluster rect.outer{rx:5px;ry:5px;}#mermaid-svg-bZvCVOxmXvZITNKC .statediagram-state .divider{stroke:#9370DB;}#mermaid-svg-bZvCVOxmXvZITNKC .statediagram-state .title-state{rx:5px;ry:5px;}#mermaid-svg-bZvCVOxmXvZITNKC .statediagram-cluster.statediagram-cluster .inner{fill:white;}#mermaid-svg-bZvCVOxmXvZITNKC .statediagram-cluster.statediagram-cluster-alt .inner{fill:#f0f0f0;}#mermaid-svg-bZvCVOxmXvZITNKC .statediagram-cluster .inner{rx:0;ry:0;}#mermaid-svg-bZvCVOxmXvZITNKC .statediagram-state rect.basic{rx:5px;ry:5px;}#mermaid-svg-bZvCVOxmXvZITNKC .statediagram-state rect.divider{stroke-dasharray:10,10;fill:#f0f0f0;}#mermaid-svg-bZvCVOxmXvZITNKC .note-edge{stroke-dasharray:5;}#mermaid-svg-bZvCVOxmXvZITNKC .statediagram-note rect{fill:#fff5ad;stroke:#aaaa33;stroke-width:1px;rx:0;ry:0;}#mermaid-svg-bZvCVOxmXvZITNKC .statediagram-note rect{fill:#fff5ad;stroke:#aaaa33;stroke-width:1px;rx:0;ry:0;}#mermaid-svg-bZvCVOxmXvZITNKC .statediagram-note text{fill:black;}#mermaid-svg-bZvCVOxmXvZITNKC .statediagram-note .nodeLabel{color:black;}#mermaid-svg-bZvCVOxmXvZITNKC .statediagram .edgeLabel{color:red;}#mermaid-svg-bZvCVOxmXvZITNKC #dependencyStart,#mermaid-svg-bZvCVOxmXvZITNKC #dependencyEnd{fill:#333333;stroke:#333333;stroke-width:1;}#mermaid-svg-bZvCVOxmXvZITNKC .statediagramTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-bZvCVOxmXvZITNKC :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} insert/upsert
flush 或达到阈值
IndexNode 构建索引
QueryNode 加载
Compaction 合并/清理
release_collection
Growing
Sealed
Indexed
Loaded
Compacted
Released

  • Growing Segment:新写入数据,通常未构建索引,查询时可能暴力搜索。
  • Sealed Segment:已封存,数据文件落到对象存储。
  • Indexed Segment:索引构建完成,适合高性能 ANN 搜索。
  • Compacted Segment:合并小 Segment 或清理删除数据后的新 Segment。

Flush、Compaction、WAL

机制 解决的问题 过度使用的代价
WAL 写入可靠性和异步消费 消息积压会影响数据可见性
Flush 将内存数据持久化为 sealed segment 频繁 flush 会产生大量小 Segment
Compaction 合并 Segment、清理删除数据 占用 IO/CPU,可能影响前台负载

完整代码

基础代码见 ../demos/basic-search,生产观察建议配合 docker compose logs -f standalone 和第 20 章监控指标阅读。

常见错误

现象 可能组件 排查方向
insert 返回慢 Proxy/DataNode/MQ 看写入吞吐、消息队列积压、批大小
search 慢 QueryNode/Proxy 看 Collection load 状态、Segment 数量、索引参数
create index 慢 IndexCoord/IndexNode 看索引任务队列、CPU/GPU、对象存储吞吐
元数据异常 RootCoord/etcd 检查 etcd 健康和磁盘空间

面试题

  1. Milvus 为什么要把 Coord 和 Node 拆开?
  2. 写入成功和可被索引搜索之间为什么可能有时间差?
  3. Segment 过碎会带来什么问题?
  4. etcd 和对象存储分别保存什么?
  5. Standalone 与 Cluster 的主要差异是什么?

练习题

  1. 启动 Milvus 后插入 10 万条随机向量,观察日志中的 Segment 和 Flush 信息。
  2. 在搜索前后分别调用 load_collectionrelease_collection,比较延迟和错误信息。
  3. 故意频繁 flush,观察搜索性能和 Segment 数量变化。

小结

理解 Milvus 架构的关键是抓住两条链路:写入链路把数据可靠地变成 Segment 和索引,查询链路把分散在多个 QueryNode 的局部结果归并成全局 TopK。后续所有调优都离不开这两条链路。

相关推荐
ting94520001 小时前
MAI-Image-2.5 技术全解:架构、核心能力与生产级部署实践
人工智能·架构
Sammyyyyy2 小时前
2026 Mac 本地大模型部署深度解析与混合架构指南
数据库·人工智能·macos·ai·架构·servbay
折哥的程序人生 · 物流技术专研2 小时前
《Java 100 天进阶之路》第93篇:Redis实战应用:缓存策略与分布式锁(2026版)
java·redis·缓存·面试·架构·求职招聘
软件技术新观察2 小时前
2026年北京大数据分析系统外包机构甄别、架构评估与售后保障
架构
heimeiyingwang2 小时前
【架构实战】网关架构设计:微服务的统一入口
微服务·云原生·架构
真实的菜2 小时前
微服务架构痛点
java·微服务·架构
大头嗯呢2 小时前
从 ACL 到零信任:权限系统设计模式的演进之路
面试·架构
MicrosoftReactor2 小时前
技术速递|以 Token 经济学驱动的架构:混合模型、AI Runway、AKS Kata MicroVM 与 MCP
人工智能·ai·架构·copilot·mcp
MemoriKu2 小时前
Flutter 相册 APP 视频模态稳定化实战:从视频抽帧、Embedding 元数据到 Android 真机启动修复
android·开发语言·前端·flutter·架构·音视频·embedding