跳到正文

Milvus 监控指标与告警 ​

一句话:Milvus 的监控要沿着「接入 → 协调 → 查询 → 数据 → 依赖」一条链看,因为它的故障通常不是单点报错,而是某个依赖变慢后,沿段、索引、加载逐级放大成查询不可用。

适用版本:Milvus 2.5.x / 2.6.x。2.6 引入 MixCoord、StreamingNode 与 Woodpecker WAL,部分组件和指标来源随之变化;指标名以实际 /metrics 输出和官方 Grafana dashboard 为准。

为什么需要 ​

Milvus 把计算和存储拆开:段文件在对象存储,元数据在 etcd,写入先过 WAL,查询节点加载索引后提供服务。这条链比单机向量库长得多,任何一环变慢都不会立刻报错,而是以「查询偶尔变慢」「collection 加载超时」「写入成功但查不到」的形式出现。只看进程存活或 /healthz,会错过整个恶化过程;必须有一条从写入到检索的端到端视角。

核心机制 ​

指标分六层看 ​

层关键指标它反映什么
接入 Proxysearch/query/insert QPS、P99 延迟、错误码与限流计数入口是否过载,失败来自客户端还是下游
协调MixCoord(2.5 为多个独立 coord)存活与选举、任务队列积压、load/release 进度元数据与调度是否卡住;协调层卡住时所有 DDL 都会超时
查询 QueryNode进程/容器内存、已加载 collection 与段数、sealed/growing 段数、search 延迟、cache 命中率查询节点的内存与扇出是否健康
数据 DataNode/StreamingNodeflush 任务数与耗时、compaction 进度、导入任务、WAL 消费延迟写入能否及时落段,growing 段能否转 sealed
依赖etcd 有无 leader、leader 切换、WAL fsync 延迟、对象存储延迟与错误率、消息队列 backlog最容易被忽略、却最先恶化的一层
索引构建构建任务进度、排队数、失败数索引建不完,collection 就无法正常加载与查询

2.6 的 Woodpecker 把 WAL 内嵌后,消息积压要看 Woodpecker 自身指标,不再有 Kafka/Pulsar 的 consumer lag;具体指标名与默认值以官方文档为准。

指标怎么连成雪崩 ​

这条链的起点常常不是 Milvus 自己,而是对象存储或 etcd。growing 段走暴力扫描,数量一多,查询延迟先涨;延迟带来重试,重试让 QueryNode 更忙;一旦 OOM,副本会重新分配,加载又要从对象存储读一遍,形成第二波压力。

五条典型恶化链路 ​

  • growing 段过多:小批量高频写入 → 段来不及 sealed → 查询同时扫索引段和增量段 → P99 上升。段数比数据总量更早反映问题。
  • 索引构建积压:导入后集中建索引,或 IndexNode 不足 → 构建排队/失败 → collection 无法 load 或只能部分加载 → 查询报未加载。
  • 对象存储变慢:flush、compaction、load 都要读对象存储 → 段无法及时 sealed、查询节点加载超时 → 写入可见性变差。
  • QueryNode 内存耗尽:加载副本过多或查询中间结果过大 → OOM/换页 → 副本重分配 → 其余节点承接更多段,连锁过载。
  • etcd 抖动:leader 频繁切换或 fsync 变慢 → 元数据操作超时 → collection 创建、load、DDL 卡住,表现为「集群像死了一样」。

资源指标之外还有两项检查:get_load_state 确认 collection 真的处于 Loaded,get_collection_stats 核对行数——写入成功不等于可查。

最小上手 ​

单机版前提:Docker Compose 能起 etcd、MinIO 与 Milvus 三个容器,本地验证足够。

bash
curl -L -o docker-compose.yml \
  https://github.com/milvus-io/milvus/releases/download/v2.6.0/milvus-standalone-docker-compose.yml
docker compose up -d
curl -s http://localhost:9091/healthz          # 期望 OK
curl -s http://localhost:9091/metrics | head   # Prometheus 文本格式

集群里每个组件默认在 9091 暴露 /metrics;把各 Pod 抓进 Prometheus 后,导入官方仓库中与版本匹配的 Grafana dashboard,比自建面板更省事。

python
from pymilvus import MilvusClient

c = MilvusClient(uri="http://localhost:19530")
print(c.get_load_state("rag"))          # 关注 state 是否为 Loaded
print(c.get_collection_stats("rag"))    # 行数是否与预期一致

关键 PromQL(指标名与 label 以实际 /metrics 为准,2.6 有重命名):

promql
# Proxy 查询 P99(直方图)
histogram_quantile(0.99,
  sum by (le) (rate(milvus_proxy_search_latency_bucket[5m])))
# 查询错误率
sum(rate(milvus_proxy_search_requests_total{status="fail"}[5m]))
  / sum(rate(milvus_proxy_search_requests_total[5m]))
# growing 段数量,按 collection 看趋势
sum by (collection) (milvus_querynode_segment_num{segment_state="Growing"})
# etcd WAL fsync P99
histogram_quantile(0.99,
  rate(etcd_disk_wal_fsync_duration_seconds_bucket[5m]))

对象存储与消息队列的指标来自 MinIO/S3 exporter 和 Kafka/Pulsar/Woodpecker:看错误率、TTFB、consumer lag 或 backlog 的趋势,而不是某一刻的绝对值。

生产动作 ​

告警清单(8–10 条) ​

告警起点(按基线校准)为什么是先兆
查询 P99超过基线 2 倍持续 5 分钟最早暴露 growing 段、对象存储或 GC 问题
查询错误率5 分钟内 > 1%可能是未加载、超时或 Proxy 限流
growing 段数单 collection 持续增长 10 分钟段无法 sealed,查询扇出与暴力扫描加重
索引构建失败/积压任一失败,或排队持续 15 分钟建不完就无法 load,查询直接不可用
QueryNode 内存working set 超 limit 的 80% 持续 10 分钟逼近 OOM;重启/副本重分配会带来第二波压力
对象存储错误率/TTFB错误率 > 1%,或 P99 明显偏离基线flush、compaction、load 同时受影响
etcd 健康无 leader、leader 频繁切换、fsync P99 超基线元数据卡住会让所有协调操作超时
WAL/消息积压backlog 持续增长 10 分钟写入积压,数据可见性变慢
collection 加载状态预期 Loaded 的 collection 变为 NotLoad查询会直接失败,且常伴随协调层异常

处置顺序 ​

  1. 先分读路径还是写路径。查询慢但 CPU 不高,优先查对象存储延迟、段数量和 compaction;写入积压则查 WAL、DataNode/StreamingNode 和对象存储。
  2. 查询变慢:先看 growing 段数与索引构建进度;入口限流、release 冷 collection 通常比立刻加 QueryNode 更快。加节点会触发段重新分配与加载,低峰做更稳。
  3. 索引积压:暂停新的批量导入,确认 IndexNode 资源与对象存储写入,再扩索引构建能力;不要在构建高峰重启协调层。
  4. QueryNode 内存告急:先 release 低优先级 collection、降低副本数或查询 limit,再扩节点;OOM 后的自动重启会重新拉取段,需预留带宽。
  5. 依赖异常与重启:etcd 抖动时避免 DDL 与大规模 load,等 leader 稳定;对象存储慢时降低写入与 compaction 并发。协调层或 QueryNode 重启会触发任务重放与段重载,通常不是第一手段。

长处与代价 ​

Milvus 的长处是专用向量检索:索引类型多(HNSW、IVF、DiskANN、量化等)、计算存储分离带来的规模弹性、原生多租户与混合检索,适合数据量和 QPS 都上来的场景。代价是:

  • 组件多、链路长,Proxy、协调、QueryNode、DataNode、etcd、对象存储、WAL 都要懂。
  • 不是通用数据库,事务、join、强约束仍在业务库;它存的是可重建的检索副本。
  • 强依赖对象存储与消息队列/WAL,依赖抖动会直接变成查询抖动;内存与运维成本高,小团队自建未必比托管便宜。
适用不适用
千万到十亿级向量、较高 QPS百万级以内且已有 PostgreSQL 的业务
多租户、需要 partition key 隔离需要事务、join、强约束的主数据存储
需要多种索引/量化/GPU 或混合检索团队没有 K8s 与分布式存储运维能力

与 pgvector、ES 的取舍 ​

维度pgvectorElasticsearchMilvus
数据规模单库能承载的量级,受 PostgreSQL 限制中大规模型,向量增大会显著吃内存大规模,计算与存储可分别扩
延迟特征同库查询、链路短,受索引与过滤影响分片扇出 + 归并,过滤聚合成熟多一跳网络与段加载,冷查询更明显
运维成本最低,复用现有数据库中高,需懂分片、堆与水位最高,组件与依赖最多
适合的前提已有 PG、要事务一致、规模不大已有 ES、关键词与向量混合规模、QPS、多租户至少有一项明显吃紧

边界 ​

  • 监控面板全绿不等于检索正确:召回质量、embedding 版本、删除是否生效,都不在资源指标里。
  • 指标名与 dashboard 强绑定版本,升级 2.6 后要重新核对;告警阈值必须按基线校准,不同索引类型、ef、过滤强度下同一 P99 的含义不同。
  • Milvus 存的是可重建副本,监控之外仍要备份 etcd 元数据与对象存储文件,并做恢复演练。
  • 上面的对比不回答「谁更强」:数据量、延迟要求、团队能力任一变化,结论都可能反转,最终以自己数据分布下的压测为准。

讲清楚 ​

Milvus 的监控要沿一条链看:Proxy 的 QPS、P99 和错误率,协调层的任务积压,QueryNode 的内存与段状态,DataNode 的 flush 与 compaction,再往下是 etcd、对象存储和 WAL。它最常见的雪崩不是某个组件挂了,而是对象存储或 etcd 变慢,导致段无法 sealed、growing 段堆积,查询被迫扫增量数据,延迟上升后引发重试,最后 QueryNode OOM、副本重分配,剩余节点继续过载。

处置要先分读写路径:查询慢先看 growing 段、索引构建和对象存储,入口限流与 release 冷 collection 往往比加节点快;写入积压则查 WAL 与 DataNode。重启会带来任务重放和段重载,通常不是第一步。Milvus 强在专用向量检索、规模与多租户,代价是组件多、依赖重、运维成本高;小规模且已有 PostgreSQL 或 ES 时,先用现成的往往更划算。

把一门技术讲透到既懂也会用