Milvus 向量检索 QPS 1 万,召回率 95%,如何把 RT 从 200 ms 降到 50 ms
解读
面试官想验证三件事:
- 对 Milvus 全链路的理解:客户端→Proxy→QueryNode→Knowhere→磁盘/内存→网络
- 能否把“200 ms→50 ms”拆成可量化的子目标,并用压测数据说话
- 是否具备“先找瓶颈再谈优化”的测试思维,而不是一上来就调参数
国内真实场景里,Milvus 多部署在阿里云 ACK、腾讯云 TKE 或裸金属 K8s 上,底层存储用 ESSD / SSD 云盘或 NVMe 本地盘,向量维度 128768,单条向量 512 B4 KB,Top-K 100 以内。压测工具一般用 locust + pymilvus 二次封装,或公司自研 Go 压测平台。SLA 通常写在“算法中台”OKR 里,RT 超标直接阻塞发版,所以答案必须“可落地、可回滚、可量化”。
知识点
- Milvus 2.x 读写路径:Proxy(GRPC)→消息队列(Pulsar/Kafka)→QueryNode→Segment(Sealed/Growing)→Knowhere(Faiss/HNSW/IVF)→CPU/GPU
- 召回率 95% 与 RT 的权衡:nprobe、ef、M、search_list、index_type 直接决定计算量
- 压测指标拆解:P99 RT = 排队延迟 + 计算延迟 + 网络序列化延迟 + 系统调度延迟
- 国内云环境常见瓶颈:ESSD 云盘最大 1 GB/s 带宽、Pod 之间跨 NUMA、GRPC 单连接 4 MB 默认窗口、iptables 性能衰减
- 可观测体系:Milvus 暴露 Prometheus 指标(query_node_sq_latency、mq_latency、cpu_seconds),结合 Grafana 看板;客户端埋点 span,用 SkyWalking 或阿里云 ARMS 做全链路
答案
“我会用‘四步法’把 RT 降到 50 ms 以内,每一步都用压测回归,确保召回率 ≥95%、QPS 1 万不倒退。”
第一步:建立基线
- 用公司 locust 框架起 30 台压测 Pod,梯度 1 k→1.2 万 QPS,每档 5 min,采集 P99 RT、CPU、GPU、队列长度、网卡 pkt_drop
- 发现 1 万 QPS 时 QueryNode CPU 68%、ESSD 读带宽 820 MB/s、Pulsar 消费延迟 18 ms,Proxy GRPC 平均 4 KB 包大小,序列化占 12 ms
- 结论:计算延迟 110 ms + 排队 35 ms + 网络 25 ms + 其他 30 ms,计算是主瓶颈
第二步:索引与参数层优化(目标砍 60 ms)
- 原 IVF_SQ8 索引,nprobe=128 → 改为 HNSW,M=48、efConstruction=200,召回率预验证 96.2%
- search_param 的 ef=128→64,召回率 95.1%,计算量降 50%,RT 降 38 ms
- 开启 Knowhere GPU,单卡 A10 替代 16 核 CPU,计算延迟再降 22 ms;GPU 与 CPU 混布,通过 nodeSelector 绑核,避免跨 NUMA
第三步:并发与链路层优化(目标砍 40 ms)
- Proxy 副本从 6→18,GRPC 线程池 core=32,max=64,连接预热,消除 18 ms 排队
- QueryNode 副本 8→16,Segment 加载策略改为 LRU2,内存命中率 94%→99%,磁盘 IO 降 45%,延迟再降 12 ms
- 开启 RDMA(阿里云 eRDMA 或裸金属 RoCE),单跳延迟 8→2 μs,网络序列化+传输 25 ms→10 ms
- 客户端批量 search,batch_size=10,降低 30% QPS 峰值,Proxy 合并请求后 RT 再降 5 ms
第四步:兜底与灰度
- 回归压测 12 小时,P99 RT 稳定 47 ms,召回率 95.3%,CPU 峰值 72%,GPU 显存 78%,满足 SLA
- 发布采用“双集群蓝绿”,旧集群 IVF_SQ8 作为冷备,一旦新集群 RT>55 ms 或召回<94%,5 分钟内切回
- 把以上所有参数固化成 Helm values,纳入 GitOps,下次版本只需改镜像 tag 即可一键回滚
拓展思考
- 如果业务方要求召回率 99%,RT 仍要 50 ms,你会如何重新设计测试方案?
- 当向量维度从 256 升到 1024,内存带宽成为瓶颈,如何在不增加成本的前提下用压测证明“必须上 GPU”?
- 国内云厂商即将下线 RDMA 公测,若网络回退到 VPC,如何量化 RT 回退幅度并提前申请预算?
- Milvus 3.x 计划去掉 Proxy,改为无状态 Sidecar,测试同学该如何改造压测脚本,保证新旧版本数据可比?