vLLM x Novita AI: 用于生产级外部 KV Cache 的 PegaFlow
TL;DR
通过与 Novita AI 合作,PegaFlow 作为以独立 Rust 进程实现的外部 KV cache 服务与 vLLM 集成。它将 KV cache 的生命周期移出了 vLLM worker 进程,实现了跨本地实例和远程节点的缓存池化,并将固定主机内存(pinned host memory)、可 RDMA 访问的远程内存和 SSD 结合成三级缓存层级结构。
为什么 KV cache 需要进程边界
KV cache 是生产级 LLM 服务中最昂贵的运行时资产之一,通常每个主机占用数百 GiB,分配和预热需要时间,并且其生命周期往往长于创建它的请求模式。 在传统的进程内设计中,KV cache 与推理引擎进程紧密耦合,这在引擎崩溃、滚动升级和模型切换时会带来痛苦,因为主机 KV 池会随着引擎重启而消失。 PegaFlow 通过将 KV cache 运行时移至每台机器上的独立守护进程来解决这个问题,该进程拥有主机 KV 池、SSD 缓存、拓扑元数据、RDMA 资源、索引状态和后台任务,而 vLLM workers 通过 CUDA IPC 和 gRPC 进行连接。 这种设计允许一个缓存服务器在同一主机上为多个引擎和多个模型提供服务,在共享相同内存池、SSD 容量和跨节点网络带宽的同时提供命名空间隔离,从而实现更清晰的故障域。
通过外部缓存所有权实现更快的重启
为了隔离主机 KV 池所有权对启动路径的影响,我们使用 dummy weights 和 eager 模式测量了运行 Qwen3-8B (TP8) 的 8 x RTX 5090 设置。 在嵌入式 KV cache 设计中,vLLM 需要 71.4 秒才能达到 ready 状态。 使用 PegaFlow,在独立服务器就绪后,vLLM 在 33.2 秒内即可达到 ready 状态,由于将长寿命的主机缓存分配与推理进程生命周期解耦,启动速度提升了 2.15 倍。
Rust 数据路径与尾延迟稳定性
将 KV cache 移至外部进程的主要动机是生命周期管理、共享和 CPU 资源隔离。 使用 Rust 实现该进程可以避免 Python 解释器开销、GIL 争用和 stop-the-world 垃圾回收,这非常重要,因为生产级缓存服务需要运行后台任务,如统计收集、索引上传、预取、健康检查、指标报告、驱逐和 SSD 缓存管理。 在 PegaFlow 中,这些任务在同一个独立的 Rust 服务中运行,不与 vLLM 共享解释器运行时,这为系统运行控制平面和维护工作提供了更多空间,而不会干扰数据平面路径。
实现跨实例和节点的缓存池化
在生产部署中,由于进程、模型或节点边界使得缓存彼此不可见,相同的逻辑 KV 内容往往被多次复制。 PegaFlow 将这些孤立的缓存碎片转变为共享缓存池。 在单个主机上,所有本地实例都连接到同一个 PegaFlow 服务器并共享一个 CPU KV 池。 在主机之间,PegaFlow MetaServer 维护一个近似的全局索引,允许节点在连接建立后,通过单边 RDMA READ 在远程端零 CPU 参与的情况下获取远程 KV 块。
单节点多实例共享
我们在一个主机上评估了八个具有相同 500 GiB 缓存预算的 Qwen3-8B 实例。
| 设置 | 缓存布局 | 吞吐量 | 平均 TTFT | 请求命中率 |
|---|---|---|---|---|
| PegaFlow | 500 GiB 共享池 | 11.97 req/s | 5.26 s | 52.35% |
| In-process | 8 x 62.5 GiB 隔离池 | 7.68 req/s | 8.22 s | 11.77% |
| 吞吐量提升了 56%,平均 TTFT 下降了 36%,请求命中率提高了 4.4 倍。 |
MLA 逻辑 KV 去重
我们还在 500 GiB 缓存预算下评估了 TP8 模式下的 DeepSeek-V3.2 MLA。
| 设置 | 缓存布局 | 吞吐量 | 平均 TTFT | 请求命中率 |
|---|---|---|---|---|
| PegaFlow | 逻辑 KV 仅存储一次 | 1.81 req/s | 35.66 s | 97.23% |
| In-process | 每个 TP rank 存储 KV | 1.05 req/s | 60.88 s | 65.18% |
| 吞吐量提升了 72%,平均 TTFT 下降了 41%,请求命中率接近该 trace 的实际上限。 |
跨节点 RDMA 共享
在一个配备了每节点 8 x 400 Gbps RDMA NIC 的内部生产推理集群中,我们对数千次最近的在线远程读取进行了采样。 对于至少 1 GiB 的大前缀拉取,PegaFlow 在生产流量下保持了 194 GB/s 的平均有效吞吐量,P99 为 250 GB/s,峰值为 261.6 GB/s。 在此传输速率下,可以在约 100 ms 内从远程节点拉取 24 GiB 的 KV cache 段,从而取代原本需要消耗数秒 GPU 时间的 prefill 计算。
三级缓存层级结构
池化使缓存容量更具实用性,但主机内存仍然是有限的。 PegaFlow 通过三级缓存层级结构来解决这个问题:热的本地块保留在 pinned DRAM 中,远程命中可以通过 RDMA 获取,而较冷的可用块可以溢出到本地 SSD。
| 层级 | 介质 | 访问路径 | 典型角色 |
|---|---|---|---|
| L1 | 本地 pinned DRAM | 本地内存 | 快速本地 KV 复用 |
| L2 | 远程 DRAM | RDMA READ | 跨节点缓存共享 |
| L3 | 本地 SSD | io_uring | 大容量溢出 |
SSD 缓存是基于 io_uring 使用 Rust 实现的。在内部测试中,单个 SSD 提供了约 6.9 GB/s 的峰值读取吞吐量,PegaFlow 在每块磁盘上保持了约 6.5-6.6 GB/s 的在线稳态吞吐量。 |
|||
| 通过多个磁盘的 RAID0,总吞吐量呈线性扩展。 | |||
| 对于扫描密集型工作负载或缓存预算较小的主机,PegaFlow 可以启用 TinyLFU 准入策略,即仅在块很可能被复用时才准入,从而保护缓存免受一次性流量的影响。 | |||
| 默认禁用 TinyLFU,因为最佳准入策略取决于工作负载的形状。 |
测量与理论命中率天花板的距离
仅凭在线命中率可能会产生误导。 PegaFlow 使用 HyperLogLog 在线估计理论命中率上限:
r* = (N - U) / N
这里,N 是窗口内的总块请求数,U 是首次出现的唯一块数量。
HyperLogLog 保持了这种估计的低成本:24 小时窗口使用的内存不到 1 MiB,误差约为 0.8%。
PegaFlow 导出滚动 HLL 窗口,默认值为 15 分钟、1 小时和 24 小时。
通过将测得的命中率和理论上限放在同一个仪表板上,操作人员可以区分三种情况:
- 缓存已接近工作负载天花板,因此增加容量可能帮助不大。
- 测得的命中率远低于天花板,表明在容量、准入、预取或跨节点发现方面有提升空间。
- 理论天花板本身很低,表明工作负载的复用率有限,瓶颈主要不在于缓存实现。
通过外部连接器与 vLLM 集成
外部 KV cache 系统通常需要对调度器、块管理器或 attention kernels 进行侵入性修改。
PegaFlow 则通过 vLLM 的外部 KV 连接器机制进行集成。
连接器通过 kv_transfer_config 进行配置,并且可以通过 kv_connector_module_path 动态加载外部包。
这使得 PegaFlow 可以在运行时接管关键的 KV cache 操作,而无需修改 vLLM 源码或维护一个长期的 fork。
从 vLLM 的角度来看,PegaFlow 并不是推理引擎的替代品;它是通过 KV 传输接口连接的外部缓存后端,而 vLLM 继续处理调度、模型执行、批处理和 OpenAI 兼容的提供服务路径。
这种边界对两个项目都有利:PegaFlow 可以独立迭代其 Rust 数据平面、SSD 缓存、RDMA 路径、索引和连接器逻辑,而 vLLM 在为外部缓存系统提供稳定的连接器契约的同时,可以继续改进核心推理引擎。
快速开始
为您的 CUDA 版本安装包:
uv pip install pegaflow-llm # CUDA 12
uv pip install pegaflow-llm-cu13 # CUDA 13
启动一个带有 pinned host memory 和 SSD 缓存的单节点 PegaFlow 服务器:
pegaflow-server \
--pool-size 30gb \
--ssd-cache-path <ssd-cache-file-path> \
--ssd-cache-capacity 512gb
对于在线部署,我们建议添加 --use-hugepages。大页(Huge pages)应提前预留。
对于多节点部署,先启动 MetaServer,然后在每个节点上启动带有 RDMA 配置的 PegaFlow 服务器。
当启用 P2P 时,每个 PegaFlow 服务器的 --addr 必须是一个可路由的 IP 地址,而不是 0.0.0.0 或 127.0.0.1,因为其他节点使用它进行 gRPC 握手和块查询。
pegaflow-metaserver --addr 0.0.0.0:50056
pegaflow-server \
--addr this-node:50055 \
--pool-size 30gb \
--ssd-cache-path <ssd-cache-file-path> \
--nics mlx5_0 mlx5_1 \
--metaserver-addr http://metaserver-host:50056
无需修改 vLLM 源码即可连接 vLLM。本文中的示例使用 vllm>=0.20.0:
vllm serve <model> \
--kv-transfer-config '{
"kv_connector": "PegaKVConnector",
"kv_role": "kv_both",
"kv_connector_module_path": "pegaflow.connector"
}'
环境变量 PEGAFLOW_HOST 和 PEGAFLOW_PORT 将连接器指向 PegaFlow 服务。默认情况下,它们是 http://127.0.0.1 和 50055。
公开参考基准测试
PegaFlow 仓库还包含一个在 H800 上使用 Llama-3.1-8B 的公开 KV cache 基准测试,使用 8 个 prompt、10K-token prefill、1-token decode 和 4.0 req/s。 在该设置下,热缓存路径将平均 TTFT 从 572.5 ms 降低到 61.5 ms,P99 TTFT 从 1113.7 ms 降至 77.0 ms。
尝试 PegaFlow
PegaFlow 已在 GitHub 上发布:novitalabs/pegaflow。该仓库包含安装说明、服务器配置、P2P RDMA 设置、指标文档和 vLLM 连接器示例。
致谢
我们要感谢 Novita AI 团队构建并实现了 PegaFlow 的生产化,感谢 vLLM 的维护者和更广泛的 vLLM 社区提供的讨论、评审和连接器基础设施,使这次集成成为可能。
Sources
相关
- Dispatch
- Dispatch
- Dispatch
- Dispatch
- Dispatch