vLLM x Novita AI:用于生产级外部 KV 缓存的 PegaFlow

13 分钟阅读
Novita AI 与 vLLM 团队

TL;DR: 我们与 Novita AI 合作,将 PegaFlow 集成为 vLLM 的外部 LLM 推理 KV Cache 服务。它作为独立的 Rust 进程实现,并通过外部 KV 连接器接口进行通信。PegaFlow 将 KV Cache 的生命周期从 vLLM 工作进程中剥离出来,在本地实例和远程节点间实现 Cache 池化,并结合固定主机内存、支持 RDMA 的远程内存以及 SSD,构建了三级 Cache 分层体系。

在面向生产环境的评估中,该设计实现了以下效果:

  • vLLM 启动速度提升 2.15 倍:当外部 Cache 服务已持有 500 GiB 主机 KV 池时。
  • 吞吐量提升 56%:8 个 Qwen3-8B 实例共享一个主机 Cache,而非使用 8 个隔离的 Cache。
  • 吞吐量提升 72%:DeepSeek-V3.2 MLA(TP8 模式)通过存储逻辑 KV 一次(而非每个 TP rank 存储一次)实现。
  • 平均远程读取吞吐量达 194 GB/s:在每个节点配置 8 x 400 Gbps 网卡的内部 RDMA 集群中,针对大前缀拉取。

核心理念很简单:KV Cache 应当是长生命周期的服务资产,而不是绑定于单个推理进程的临时状态。

对于 vLLM 用户,重要的是该集成通过现有的 kv_transfer_config 路径暴露。无需修改 vLLM 源代码或维护长期分支,即可将 PegaFlow 用作外部 Cache 后端。

为什么 KV Cache 需要进程边界

KV Cache 是生产级 LLM 服务中最昂贵的运行时资产之一。它在每台主机上可占用数百 GiB,分配和预热耗时较长,且生命周期往往长于最初创建它的请求模式。

在传统的进程内(in-process)设计中,该资产与推理引擎进程紧密耦合。这种耦合在引擎崩溃、滚动升级和模型切换时会导致严重问题。当引擎重启,主机 KV 池随之消失。当服务集群从一个模型切换到另一个模型时,可能需要重新分配并预热数百 GiB 的固定内存,才能重新处理流量。

PegaFlow 通过将 KV Cache 运行时移动到每台机器上的独立守护进程中解决了这一问题。PegaFlow 服务器拥有主机 KV 池、SSD Cache、拓扑元数据、RDMA 资源、索引状态和后台任务。vLLM 工作进程通过 CUDA IPC(数据路径)和 gRPC(本地控制路径)与本地 PegaFlow 进程通信。

Figure 1: PegaFlow runs as an external KV cache service next to vLLM. vLLM workers communicate with the local PegaFlow server through CUDA IPC and gRPC, while PegaFlow manages pinned memory, SSD cache, RDMA transfer, and optional cross-node indexing through the MetaServer.
图 1:PegaFlow 作为 vLLM 的外部 KV Cache 服务运行。vLLM 工作进程通过 CUDA IPC 和 gRPC 与本地 PegaFlow 服务器通信,而 PegaFlow 通过 MetaServer 管理固定内存、SSD Cache、RDMA 传输和可选的跨节点索引。

该设计基于一个生产需求构建:一个 Cache 服务器应能同时为同一主机上的多个引擎和多个模型提供服务。不同的模型、张量并行配置和引擎版本可以在一个 PegaFlow 进程下通过命名空间隔离共存,同时共享相同的内存池、SSD 容量和跨节点网络带宽。

由此产生的故障域更为清晰。vLLM 进程可以崩溃、升级或切换模型,而 Cache 服务保持活跃。反之,Cache 层的问题也不会导致推理引擎进程宕机。

通过外部 Cache 所有权实现更快的重启

为了隔离主机 KV 池所有权对启动路径的影响,我们测试了运行 Qwen3-8B(TP8)的 8 x RTX 5090 设置。实验使用虚拟权重和 eager 模式以消除权重加载和编译的影响,专注于大约 500 GiB 主机 KV 池的效果。

在嵌入式 KV Cache 设计中,500 GiB 池由 vLLM 工作进程拥有,vLLM 达到就绪状态耗时 71.4 秒

使用 PegaFlow 时,500 GiB 池由独立的 PegaFlow 服务器预先拥有。服务器就绪后,vLLM 在 33.2 秒 内达到就绪状态。通过将长寿命的主机 Cache 分配与推理进程生命周期解耦,启动速度提升了 2.15 倍

Figure 2: vLLM startup time with a 500 GiB host KV pool. Keeping the pool in the external PegaFlow server cuts the vLLM startup path from 71.4 seconds to 33.2 seconds in this setup.
图 2:具有 500 GiB 主机 KV 池的 vLLM 启动时间。将池保存在外部 PegaFlow 服务器中,在此设置下,vLLM 启动路径从 71.4 秒缩短至 33.2 秒。

Rust 数据路径与尾延迟稳定性

将 KV Cache 移至外部进程的主要动机是生命周期管理、共享和 CPU 资源隔离。用 Rust 实现该进程还带来了重要的操作优势:延迟稳定性。

PegaFlow 的数据平面避免了 Python 解释器开销、GIL 争用和“全停”(stop-the-world)垃圾回收。这一点至关重要,因为生产级 Cache 服务不仅要在关键路径上移动字节,还要运行统计收集、索引上传、预取、健康检查、指标报告、驱逐和 SSD Cache 管理等后台任务。

在 PegaFlow 中,这些任务在独立的 Rust 服务中运行,不与 vLLM 共享解释器运行时。这使系统有更多余地运行控制平面和维护工作,而不会干扰数据路径。

Figure 3: Tail and average latency comparison under baseline and GIL-load conditions. The Rust Tokio path is much less affected by background load than the Python uvloop and Python ZMQ baselines.
图 3:基准状态和 GIL 负载条件下的尾延迟与平均延迟对比。Rust Tokio 路径受后台负载的影响远小于 Python uvloop 和 Python ZMQ 基线。

跨实例和节点的 Cache 池化

在生产部署中,由于进程、模型或节点边界使得 Cache 相互不可见,相同的逻辑 KV 内容往往会被多次复制。

这种模式常见于以下几种部署场景:

  • 主机上的多个小模型实例:在 8-GPU 主机上运行 8 个 Qwen3-8B 实例,可能会存储 8 次相同的系统提示词。
  • 广泛的专家并行(Expert-Parallel)部署:同一机器上的多个数据并行副本即使运行在同一物理主机上,也维持着独立的 Cache。
  • 带有张量并行(TP)的 MLA:对于 DeepSeek-V3.2 等模型,逻辑潜在 KV 可以存储一次,但进程内的 TP8 部署可能在每个 rank 上物理存储一次。
  • 跨节点调度:如果节点 A 负载过高导致请求被路由到节点 B,即使节点 A 有缓存命中,也可能导致前缀被重新计算。

PegaFlow 将这些孤立的缓存碎片转化为一个共享的 Cache 池。

在单台主机上,所有本地实例连接到同一个 PegaFlow 服务器并共享一个 CPU KV 池。对于多实例小模型服务、WideEP 数据并行副本和 TP 工作进程,相同的块可以物理上仅存储一次,并被多个引擎重用。

跨主机时,PegaFlow MetaServer 维护一个近似的全局索引。节点可以通过单侧 RDMA READ 获取远程 KV 块,在连接建立后远程端无需 CPU 参与。因此,远程命中可以像本地命中一样发挥作用,避免昂贵的前缀重新计算。

结果

以下实验保持 Cache 预算不变,仅改变 Cache 在 vLLM 进程、张量并行 rank 或节点间的可见性。

单节点多实例共享

我们评估了同一主机上 8 个 Qwen3-8B 实例在相同 500 GiB Cache 预算下的表现。

设置Cache 布局吞吐量平均首字延迟 (TTFT)请求命中率
PegaFlow500 GiB 共享池11.97 req/s5.26 s52.35%
进程内8 x 62.5 GiB 隔离池7.68 req/s8.22 s11.77%

重点不在于系统使用了更多内存(事实并非如此)。相同的 500 GiB 预算变得更加有效,因为请求可以从一个共享池中提取,而非 8 个隔离池。吞吐量提高了 56%,平均 TTFT 下降了 36%,请求命中率提升了 4.4 倍

MLA 逻辑 KV 重复数据删除

我们还评估了 500 GiB Cache 预算下 DeepSeek-V3.2 MLA (TP8) 的表现。

设置Cache 布局吞吐量平均首字延迟 (TTFT)请求命中率
PegaFlow逻辑 KV 存储一次1.81 req/s35.66 s97.23%
进程内KV 按 TP rank 存储1.05 req/s60.88 s65.18%

对于此工作负载,避免在 TP rank 间重复存储有效地扩大了可用缓存容量。吞吐量提高了 72%,平均 TTFT 下降了 41%,请求命中率达到了该跟踪数据的实际上限。

Figure 4: Summary of the two fixed-budget local sharing experiments. In both cases, PegaFlow improves effective cache capacity by making the same KV budget visible across isolation boundaries.
图 4:两个固定预算本地共享实验的总结。在这两种情况下,PegaFlow 都通过使相同的 KV 预算跨越隔离边界可见,从而提升了有效缓存容量。

跨节点 RDMA 共享

在每个节点配备 8 x 400 Gbps RDMA 网卡的内部生产推理集群中,我们采样了数千次近期的在线远程读取。对于至少 1 GiB 的大前缀拉取,PegaFlow 在生产流量下维持了 194 GB/s 的平均有效吞吐量,P99 吞吐量为 250 GB/s,峰值达到 261.6 GB/s

以此传输速率,一个 24 GiB 的 KV Cache 片段可以在约 100 毫秒内从远程节点拉取。这可以取代原本需要数秒 GPU 时间的前缀计算。在实践中,这就是远程命中具备价值的原因:它们不仅是“比未命中好”,其速度足以充当服务路径的一部分。

Figure 5: Effective throughput for large remote KV cache reads in an internal production cluster. At the measured average throughput, a 24 GiB remote KV segment can be fetched in roughly 100 ms.
图 5:内部生产集群中大远程 KV Cache 读取的有效吞吐量。以测得的平均吞吐量计算,24 GiB 远程 KV 段可在约 100 毫秒内获取。

三级 Cache 分层

池化使缓存容量更有价值,但主机内存毕竟有限。长重用距离的前缀可能在下次使用前被驱逐,而简单的 LRU 可能被扫描式流量(其中大量一次性块通过系统)严重干扰。

PegaFlow 通过三级缓存分层解决此问题。热点本地块保留在固定 DRAM 中,远程命中可以通过 RDMA 获取,较冷的重用块可以溢出到本地 SSD。

层级介质访问路径典型角色
L1本地固定 DRAM本地内存快速本地 KV 重用
L2远程 DRAMRDMA READ跨节点 Cache 共享
L3本地 SSDio_uring大容量溢出

SSD Cache 是基于 io_uring 用 Rust 实现的。在内部测试中,单块 SSD 提供了约 6.9 GB/s 的峰值读取吞吐量。PegaFlow 将在线稳定状态的吞吐量保持在每磁盘 6.5-6.6 GB/s 左右,以 5% 的峰值带宽换取更稳定的尾延迟。通过多个磁盘组成 RAID0,总吞吐量基本呈线性扩展。

对于扫描密集型工作负载或缓存预算较小的主机,PegaFlow 可以启用 TinyLFU 准入策略。该策略仅在块可能被重用时才接纳它们,从而保护缓存免受一次性流量的影响。

TinyLFU 默认处于禁用状态,因为最佳准入策略取决于工作负载形态。然而,在多个内部跟踪中,当缓存较小或扫描压力较大时,它显著优于 LRU。

Figure 6: Cache-policy comparison under small cache sizes. Scan-heavy traces can make simple recency-based policies ineffective, while admission-aware policies such as TinyLFU can protect the cache from one-time blocks.
图 6:小缓存容量下的缓存策略比较。扫描密集型跟踪可能使简单的基于近期性的策略失效,而感知准入的策略(如 TinyLFU)可以保护缓存免受一次性块的侵占。

衡量与理论命中率上限的差距

在线命中率本身可能具有误导性。对于重用率极低的工作负载,3% 的命中率可能算好;而如果工作负载的理论上限高得多,90% 的命中率仍有提升空间。

对于运维人员而言,有意义的问题不仅是“命中率是多少?”,而是“我们距离该工作负载理论上能实现的最佳命中率还有多远?”

PegaFlow 在线使用 HyperLogLog 估算理论命中率上限。

r* = (N - U) / N

其中 N 是窗口内的块请求总数,U 是首次见到的唯一块数量。HyperLogLog 使得此估算成本很低:24 小时窗口占用内存小于 1 MiB,误差约为 0.8%。

PegaFlow 导出滚动 HLL 窗口,默认值为 15 分钟、1 小时和 24 小时。通过将测得的命中率与理论上限置于同一仪表板上,运维人员可以区分三种情况:

  • 缓存已接近工作负载天花板,增加容量可能作用有限。
  • 测得的命中率远低于上限,表明在容量、准入策略、预取或跨节点发现方面仍有优化空间。
  • 理论上限本身很低,表明工作负载重用率受限,瓶颈主要不在缓存实现上。

通过外部连接器与 vLLM 集成

外部 KV Cache 系统通常需要对调度程序、块管理器或 Attention 核进行侵入式更改。PegaFlow 则通过 vLLM 的外部 KV 连接器机制集成。

连接器通过 kv_transfer_config 配置,外部包可以通过 kv_connector_module_path 动态加载。这使得 PegaFlow 可以在运行时接管关键的 KV Cache 操作,而无需修改 vLLM 源代码或携带长寿命的分支。

从 vLLM 的角度来看,PegaFlow 并不是服务引擎的替代品,而是通过 KV 传输接口附加的外部 Cache 后端,而 vLLM 继续处理调度、模型执行、批处理和兼容 OpenAI 的服务路径。

这一边界对两个项目都有益。PegaFlow 可以独立迭代其 Rust 数据平面、SSD Cache、RDMA 路径、索引和连接器逻辑。vLLM 可以继续改进核心服务引擎,同时为外部 Cache 系统暴露稳定的连接器契约。

快速入门

安装对应 CUDA 版本的包

uv pip install pegaflow-llm        # CUDA 12
uv pip install pegaflow-llm-cu13   # CUDA 13

启动一个带有固定主机内存和 SSD Cache 的单节点 PegaFlow 服务器

pegaflow-server \
  --pool-size 30gb \
  --ssd-cache-path <ssd-cache-file-path> \
  --ssd-cache-capacity 512gb

对于在线部署,我们建议添加 --use-hugepages。大页内存应提前预留。它们可以加速 CPU 固定内存分配,并通过在注册和传输过程中降低地址转换开销来减少 RDMA MTT 压力。

对于多节点部署,请先启动 MetaServer,然后在每个节点上启动配置了 RDMA 的 PegaFlow 服务器。启用 P2P 时,每个 PegaFlow 服务器的 --addr 必须是可路由的 IP 地址,不能是 0.0.0.0127.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_HOSTPEGAFLOW_PORT 环境变量将连接器指向 PegaFlow 服务。默认分别为 http://127.0.0.150055

公开参考基准测试

PegaFlow 仓库还包含一个在 H800 上使用 Llama-3.1-8B 的公开 KV Cache 基准测试,使用 8 个提示词、10K-token 前缀填充、1-token 解码和 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 社区提供的讨论、审核以及使这一集成成为可能的连接器基础设施。