向量检索边缘化:在香港服务器上落地 Milvus / pgvector 的冷热分层与 NVMe Pool + RDMA 直通

那天晚上 23:40,香港到东京的 RTT 稳定在 45ms 左右,但真实用户的向量召回链路一旦绕行到核心区的“统一大库”,尾延迟就像被人拽住脚踝。我们的召回服务在云上,embedding 在云上,向量索引也在云上,唯独用户在香港。A/B 面板给我看,一半流量在 95 分位卡到 350ms——这不是我能接受的数字。
我盯着机柜里两台新上的 NVMe 盒子发呆:一组满血的 U.2 盘,旁边是两张亮着蓝灯的 ConnectX 网卡。我脑子里只有一句话:把检索推到边缘,把热数据钉在 NVMe 上,用 RDMA 把吞吐和延迟都榨出来。于是,就有了下面这套方案与踩坑记录。
1. 目标与路线图
业务目标
-
P95 向量检索延迟 ≤ 80ms(端到端,香港用户,TopK=50,查询向量维度 768/1024)
-
热数据 100% 命中边缘,冷数据回落不超过 300ms
-
单集群吞吐 ≥ 8k QPS,峰值≥ 12k QPS(只读阶段)
-
故障演练覆盖:单盘/单网卡/单节点/单交换机/单可用区失效
技术路线
-
存储层:NVMe Pool 以 NVMe-oF (RDMA/RoCEv2) 暴露卷;本地/远端混合池化
-
引擎层:Milvus(2.x)负责“热检索 + 冷分层至对象存储”,PostgreSQL + pgvector 负责元数据/回查与一部分通用相似度检索(以 SQL 能力补齐)
-
冷热分层:Milvus 的 segment/索引放 热层 NVMe,冷层 MinIO(S3 兼容);pgvector 通过 Tablespace 做表/索引的冷热 tablespace 迁移
-
网络:25/100GbE RoCEv2 RDMA,PFC + ECN,Jumbo Frame;业务网与存储网物理/逻辑隔离
-
编排:Kubernetes + Helm 部署 Milvus 组件;PostgreSQL 裸机+Patroni(或单机起步,后期再切)
-
操作系统:CentOS 7.9(内核升级至 ELRepo kernel-ml 以便更好的 RDMA/NVMe 驱动支持)
2. 机房与硬件清单(落地可复用)
注:以下为我最终上线时的 实际可行 配置,不是实验室“神机”。预算友好、可替换。
2.1 角色与节点规格
| 角色 | 数量 | CPU | 内存 | 本地存储 | 网络 | 备注 |
|---|---|---|---|---|---|---|
| NVMe-oF Target(存储池) | 2 | 2×Xeon Silver 4310 | 256GB | 8×3.84TB U.2 NVMe(RAID0 by SPDK/VOL) | 2×100GbE ConnectX-6(RoCEv2) | 负责 RDMA 暴露卷 |
| Milvus Query/Index Node | 3 | 2×Xeon Silver 4310 | 256GB | 2×1.92TB NVMe(本地缓存) | 2×25GbE ConnectX-5 | 可选 1×A10 GPU(可选) |
| Milvus Meta / etcd / Pulsar / MinIO | 3 | 1×Xeon Silver 4210 | 128GB | 2×960GB SSD(RAID1) | 2×25GbE | 可合并/拆分 |
| PostgreSQL + pgvector | 2(主备) | 1×Xeon Gold 6230 | 256GB | 系统盘+2×3.84TB NVMe(Tablespace 热层) | 2×25GbE | Patroni/keepalived |
| 汇聚/监控 | 2 | 任意 | 64GB | 2×480GB SSD | 2×10GbE | Prom+Grafana+Loki |
交换机:
-
TOR:Mellanox SN2010(或等价 25/100GbE),启用 PFC/ECN
-
核心:任意兼容 100GbE,上行 LAG
2.2 操作系统与固件
-
CentOS 7.9(注意 EOL,生产请上内核新版本):
-
固件:升级 NVMe 固件、MLX 网卡固件到供应商建议的稳定版本(机房窗口操作)
3. 网络拓扑与关键参数
3.1 逻辑拓扑(简化)
3.2 网络参数(RoCEv2 推荐)
| 项 | 值/建议 |
|---|---|
| MTU | 9000(端到端一致:主机、交换机、容器 CNI) |
| RDMA | RoCEv2(基于 UDP 的 L3 可路由) |
| 流控 | PFC(优先级 3)+ ECN(交换机开启,DiffServ 映射) |
| 优先级 | DSCP=26(示例),网卡/交换机/主机一致映射到 RoCE 队列 |
| 中断亲和 | irqbalance 关闭,手动绑核(见后文) |
| NUMA | QueryNode/IndexNode 绑到与 RDMA 网卡同一 NUMA 域 |
| 监控 | mlx5 exporter / rdma 计数器、PFC pause 统计 |
主机侧 RDMA 简要配置
4. NVMe Pool + RDMA 直通(NVMe-oF + SPDK)
4.1 NVMe-oF Target 部署
前置:Hugepage & DPDK
编译/安装 SPDK(精简示例)
SPDK NVMe-oF Target 配置(nvmf_target.json 片段)
Target 运行
4.2 Initiator(Milvus/PG 节点)挂载卷
注意
-
NVMe-oF target 双机做 一致性与多路径:使用
nvme multipath -i on并在业务低峰做 failover 演练。 -
观察
nvme reconnect行为,必要时设置ctrl loss tmo。
5. Milvus:热在 NVMe,冷在 MinIO(S3)
5.1 部署(Kubernetes + Helm,关键 values)
存储与分层核心参数(示例):