跳到主要内容

Mooncake

Kimi 如何用 KVCache 中心化重构推理架构,实现集群级 KV 池化与调度

核心要点

  • 核心理念:把 KVCache 抬升为系统一等公民,物理层 PD 分离 + 集群级共享 KV pool + Conductor 全局调度
  • 四层组件:Conductor (调度) + Prefill/Decode cluster (计算) + Mooncake Store (KV pool) + Transfer Engine (传输)
  • CPP (Chunked Pipeline Parallelism):长 prompt 切 chunk 多节点流水,比 SP 通信少
  • Layer-wise prefill + 异步推送:prefill 算完一层立即推送,与下一层计算 overlap
  • Cache-aware + load-aware 调度:cost = 传输 + prefill + 队列等待;prediction-based early rejection
  • 关键数据:Kimi trace +75% 请求量;16k-128k 长上下文 +50% ~ +525% 吞吐

Mooncake 是 Moonshot AI 为 Kimi 大模型推理服务自研、2024 年 6 月公开技术报告、2025 年 2 月在 USENIX FAST '25 获 Best Paper Award 的推理服务平台[1]。本文整理 Mooncake 的设计动机、组件分工、PD 分离实现、KVCache 池化与传输、调度算法、实测数据。

设计动机是什么

核心问题:Kimi 流量哪两个突出特征驱动了 KV-centric 设计?

Mooncake 的设计选择针对 Kimi 在线服务的两个突出特征。

流量长且重复:FAST '25 论文实测的真实 trace (23,000 条请求) 显示平均输入约 7,955 token、平均输出约 194 token,且约 50% 的请求与历史 prefix 有可复用 KVCache — 这是 chatbot 多轮对话与 system prompt 共享的天然特征。论文中两个公开评测集进一步给出极端值:L-Eval 平均 19,019 token 输入、>80% prefix 复用率;arXiv summarization 平均 8,088 token 输入、近 0% 复用率[1]

流量指数增长:Moonshot 在 2024 上半年单服务 DAU 快速攀升,过载已成常态。在这种"既有大量重复、又必然周期性过载"的工况下,传统 colocated 方案有两个痛点:

  • prefill 与 decode 共享 GPU,长 prompt 一来就把 decode 的 batch 拖慢,违反 TBT SLO
  • KVCache 仅在单实例本地内存,相同 system prompt 的请求落到不同实例就要重算 prefill,浪费算力

Mooncake 的回答:把 KVCache 从单 GPU HBM 解耦出来变成集群级共享资源,再围绕它重新切分计算。这一思路与同期工业界的 Splitwise (Microsoft) / DistServe (UCSD) 同属 PD-disagg 系,但 Mooncake 独有的是把 KVCache 池化做到生产规模,并由 Conductor 做 cache-aware 全局调度。

总体架构怎么分工

核心问题:三层组件 (调度 + 计算 + 存储) + 网络层怎么协同?单请求生命周期是什么?

Mooncake 在物理上是三个层次:

组件角色资源
调度层Conductor (单逻辑实例 / 高可用副本)接请求、查 prefix cache、选 (P, D) 实例对、下发控制面
计算层Prefill cluster + Decode cluster分别做 prefill 与 decodeGPU HBM
存储层Mooncake Store (跨节点 KVCache pool)按 block 存放 KVCache,支持多副本、SSD 冷分层CPU DRAM + 本地 NVMe SSD
网络层Transfer Engine跨节点搬 KVCache 张量RDMA (IB/RoCE/eRDMA) / NVLink / NVMe-oF / TCP

@tbl-mooncake-layers Mooncake 四层架构

来源:arXiv:2407.00079 §3 (Architecture Overview); github.com/kvcache-ai/Mooncake README。

单请求生命周期 (论文 Algorithm 1 与 §4):

  1. 客户端发起请求 → Conductor 收到 prompt token IDs
  2. Conductor 对 prompt 按 block 算 hash,查全局 prefix cache table,得到每个 prefill 实例的最长前缀命中长度
  3. Conductor 用 cost function 选出 (P, D): cost = 缓存传输时间 + 增量 prefill 时间 + decode 队列等待时间
  4. P 实例从 Store / 其它 P 实例拉缺失的 KVCache 块到本地 (Transfer Engine 操作)
  5. P 实例做 chunked-pipeline prefill;每算完一层就异步推该层 KVCache 给 D 实例 (layer-wise overlap)
  6. D 实例收到首 token 的 KVCache 后开始 decode,逐 token 出结果回客户端
  7. 新生成的 KVCache block 由 Transfer Engine 异步写回 Store,并向 Conductor 发布 BlockStored 事件

Conductor 后续维护:监听各推理引擎通过 ZMQ 发出的 BlockStored / BlockRemoved 事件,更新 prefix cache 表与副本数。

PD 分离怎么具体实现

核心问题:Prefill / Decode 集群在硬件 / batching / 并行四个维度的差异化是什么?CPP 和 Layer-wise prefill 怎么用?

PD 分离的核心是把"什么硬件适合什么阶段"的不对称利用起来,Mooncake 在四个维度做了切分:

维度Prefill 集群Decode 集群
主要负载大矩阵乘 (compute-bound)KVCache 读 + 小矩阵乘 (memory-bound)
适合硬件高算力 GPU (H100 等)高显存带宽 + 大 HBM (H200 等)
Batching 策略单请求切 chunk 流水化,不强调跨请求 batchcontinuous batching,跨请求拼大 batch 摊薄 KV 读
并行策略Chunked Pipeline Parallelism (CPP)TP + DP

@tbl-mooncake-pd PD 分离的四个差异化维度

CPP (chunked pipeline parallelism) 解决长 prompt 在单节点 prefill 时延过大的问题。论文 §4.1 给出的方案:把输入按 prefill_chunk (典型 >1000 token) 切块,多节点按流水方式分别处理不同 chunk。相比 sequence parallelism (SP), CPP 只在 chunk 边界做通信,不需要每个 attention head 都 all-gather,显著降低跨节点带宽需求。思路追溯到 Tera-Pipe (Li et al., 2021)。

Layer-wise prefill + 传输 overlap 是减小端到端 TTFT 的另一关键:prefill 实例每算完一层就启动该层 KVCache 的异步推送,下一层计算与上一层传输 overlap,理想情况下端到端时间近似 max(传输时间,计算时间) 而非二者之和。论文 Figure 5 给出该机制的实测验证。

KVCache 池化与传输怎么做

核心问题:Mooncake Store 是什么结构?Transfer Engine 支持哪些协议?

Mooncake Store

按 KV block 分对象存储 (block 通常对应 16 / 32 / 256 个 token,由 inference engine 配置)。每个对象的元数据由 Master Service (独立服务) 统一管理,包含:

  • 对象的 block hash (Conductor prefix 查询的 key)
  • 所有副本所在节点 + 介质 (HBM / DRAM / SSD)
  • lease 与引用计数 (用于 LRU 与延迟 GC)
  • 副本数策略 (热点对象主动多副本)

Store 暴露 Put / Get / BatchTransfer 接口给 inference engine,对计算侧透明。

Transfer Engine

Mooncake 把"跨节点搬张量"这件事抽成独立项目 Transfer Engine (旧名 Messenger),统一封装多种底层协议:

协议适用场景备注
TCP兜底 / 跨数据中心不需要 RDMA NIC
RDMA (InfiniBand)同 IB fabric 内部单向延迟 µs 级
RDMA (RoCEv2)以太网 + lossless 配置部署最广
RDMA (eRDMA)阿里云弹性 RDMA公有云专用
NVLink / NVLink-C2C同 NVL 域内 GPU↔GPU走 GPUDirect
NVMe-oF与远端 SSD 直通冷分层 Store 用
CXL内存语义远端 DRAM较新硬件
EFAAWS 实例AWS Trn1 / P4d

@tbl-mooncake-protocols Transfer Engine 支持的传输协议

工程语义层面,Transfer Engine 提供 batched async API,自动按 topology 选最优路径 (同机内走 NVLink、同 fabric 走 RDMA、跨 zone 走 TCP),且支持 GPU buffer 直收直发 (GPUDirect RDMA) 避免一次 host bounce。

Conductor 调度算法是什么

核心问题:Cost function 三项 + hot-spot replication + early rejection 各自做什么?

Conductor 选 (P, D) 对的代价函数综合三项:缓存复用收益、prefill 计算开销、decode 队列负载。FAST '25 论文 Algorithm 1 (cache-aware prefill scheduling) 的关键步骤:

  1. 输入:请求 R 的 prompt token IDs;输出:(p, d)
  2. 对 prompt 按 block_size 切块、算 hash → 得到 block_hash 列表
  3. 对每个 prefill 实例 p:
    • 查 prefix cache table,得到 p 上的最长命中前缀长度 hit_len(p)
    • 估算 prefill_time(p) = f(prompt_len - hit_len(p)) (论文用经验拟合曲线)
    • 估算 transfer_time(p) = 缺失 block 数 × block 大小 / 链路带宽
    • 估算 queue_wait(p) = 该实例当前队列累积 prefill 时长
  4. argmin_p (transfer_time(p) + prefill_time(p) + queue_wait(p))
  5. 对每个 decode 实例 d,估其 TBT 预期;选满足 SLO 且负载最低者
  6. 若热点 KVCache 被反复命中同一 p,主动触发 hot-spot replication (多副本写到其它 p)

Load-aware / 早期拒绝:论文 §4.4 引入 prediction-based early rejection。Conductor 维护一个"未来 t 时刻 decode cluster 负载"的预测模型 (基于"每请求 decode 时长近似均匀"假设),在 prefill 前就估算请求被接到 decode 时是否会违反 TBT SLO;若会则直接拒绝、不浪费 prefill 算力。论文 Figure 8 显示这能避免 prefill 与 decode 负载之间的"先 prefill 完再被拒"震荡。

Conductor 当前演进:根据仓库 issue #977 (RFC, 2025-10), Conductor 正从单一调度器演化为开放的 KV indexer + router 接口,目标是让 vLLM / SGLang 等外部 inference engine 通过 HTTP /query / /register / /unregister API 把自己的 prefix cache 注册进来共享。

公开性能数据是多少

核心问题:各 workload 下 Mooncake 相比 vLLM 的吞吐 / SLO 提升是多少?

下表汇总论文 §6 给出的实测数据,所有数字均来自 arXiv:2407.00079 v1

评测配置对比基线Mooncake 收益
arXiv summarizationMooncake 3P+1DvLLM 4M吞吐 +20%
L-Eval (长上下文)Mooncake 3P+1DvLLM 4M吞吐 +40%
模拟 16k–128k 长上下文Mooncake 3P+1DvLLM 4M吞吐 +50% ~ +525%
Real Kimi trace 重放Mooncake 10P+10DvLLM 20M多处理 +75% 请求 而不破 SLO
过载场景 2× 重放 (23,000 条请求;三行横向对比同集群下三种 ER 策略)Mooncake 8P+8D,无 ER拒绝 4,183 条
过载场景 2× 重放 (同上)Mooncake 8P+8D, basic ER拒绝 3,771 条
过载场景 2× 重放 (同上)Mooncake 8P+8D, prediction ER拒绝 3,589 条

@tbl-mooncake-results 公开实测数据

解读要点

  • 长上下文场景 (16k+) 收益最大,因为这正是 PD 分离 + 池化 KVCache 节省最多算力的工况
  • "+75% requests" 是论文最常被引用的整体数字,但前提是 1:1 P/D 比例 + 真实 Kimi trace + 同样 SLO
  • prediction-based ER 比 basic ER 又减少 ~5% 拒绝量,差距不大;论文承认主要价值是避免 SLO 抖动而非绝对吞吐

后续 ACM TOS 期刊版 (DOI 10.1145/3773772, 2025-11) 与 FAST '25 presentation 版补充了 Mooncake Store 在生产环境的命中率与冷分层数据,但核心 PD 数字未变。

跟同期工作和原始论文什么关系

核心问题:Mooncake 演进时间线 + 与 Splitwise / DistServe / vLLM / SGLang 的关系?

工程演进时间线

版本 / 节点时间关键变化
arXiv v12024-06首次披露架构,含 Conductor / Transfer Engine / Store 三组件 + Algorithm 1
GitHub 开源 (kvcache-ai/Mooncake)2024 下半年先开源 Transfer Engine
FAST '25 Best Paper2025-02同社区第一篇 PD-disagg + KVCache pool 联合方案
Mooncake Store 开源2025-03Store 独立项目,与 vLLM xPyD PD-disagg 后端联调
Conductor RFC (#977)2025-10Conductor 公开化、走 HTTP API、与 SGLang / vLLM 共享 prefix cache
ACM TOS 期刊版2025-11增加 Store 生产数据
PyTorch Ecosystem2026 初Mooncake 加入 PyTorch 官方生态

@tbl-mooncake-timeline Mooncake 工程演进时间线

与同期工作的关系

  • Splitwise (Patel et al., ISCA '24):同样 PD 分离,但每实例自带 KVCache、不做池化;Mooncake 借鉴了 PD 分离原则但加上池化
  • DistServe (Zhong et al., OSDI '24):同样 PD 分离 + SLO-aware 调度,更偏理论建模;Mooncake 偏工程落地
  • vLLM PagedAttention:解决 单机 KVCache 内存碎片,与 Mooncake 互补;vLLM 已通过 xPyD 后端接入 Mooncake Store
  • SGLang RadixAttention:单机前缀树共享 KVCache; Conductor 演进后可让 SGLang 把 radix 树注册到全局 indexer

Takeaway

知识点核心结论
核心理念KVCache 抬升为一等公民,PD 分离 + 集群级 KV pool + cache-aware 全局调度
四层组件Conductor + Prefill/Decode cluster + Mooncake Store + Transfer Engine
CPP长 prompt 切 chunk 多节点流水,比 SP 通信少,chunk 边界才通信
Layer-wise prefill算完一层异步推送,与下一层计算 overlap,端到端 ≈ max(传输,计算)
Transfer Engine 8 协议TCP / IB / RoCEv2 / eRDMA / NVLink / NVMe-oF / CXL / EFA
Cost functionargmin (transfer + prefill + queue_wait),配 hot-spot replication
Prediction-based ER预测 decode 是否违反 TBT SLO,提前拒绝避免浪费 prefill
关键数据Kimi trace +75%; 16k-128k 长上下文 +50% ~ +525% (vs vLLM 4M)

参考资料

  1. Qin R, Li Z, He W, et al. Mooncake: A KVCache-centric Disaggregated Architecture for LLM Serving. arXiv:2407.00079, 2024-06. https://arxiv.org/abs/2407.00079