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 与 decode | GPU 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):
- 客户端发起请求 → Conductor 收到 prompt token IDs
- Conductor 对 prompt 按 block 算 hash,查全局 prefix cache table,得到每个 prefill 实例的最长前缀命中长度
- Conductor 用 cost function 选出 (P, D): cost = 缓存传输时间 + 增量 prefill 时间 + decode 队列等待时间
- P 实例从 Store / 其它 P 实例拉缺失的 KVCache 块到本地 (Transfer Engine 操作)
- P 实例做 chunked-pipeline prefill;每算完一层就异步推该层 KVCache 给 D 实例 (layer-wise overlap)
- D 实例收到首 token 的 KVCache 后开始 decode,逐 token 出结果回客户端
- 新生成的 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 流水化,不强调跨请求 batch | continuous 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 | 较新硬件 |
| EFA | AWS 实例 | 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) 的关键步骤:
- 输入:请求 R 的 prompt token IDs;输出:(p, d)
- 对 prompt 按 block_size 切块、算 hash → 得到 block_hash 列表
- 对每个 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 时长
- 选
argmin_p (transfer_time(p) + prefill_time(p) + queue_wait(p)) - 对每个 decode 实例 d,估其 TBT 预期;选满足 SLO 且负载最低者
- 若热点 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 summarization | Mooncake 3P+1D | vLLM 4M | 吞吐 +20% |
| L-Eval (长上下文) | Mooncake 3P+1D | vLLM 4M | 吞吐 +40% |
| 模拟 16k–128k 长上下文 | Mooncake 3P+1D | vLLM 4M | 吞吐 +50% ~ +525% |
| Real Kimi trace 重放 | Mooncake 10P+10D | vLLM 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 v1 | 2024-06 | 首次披露架构,含 Conductor / Transfer Engine / Store 三组件 + Algorithm 1 |
| GitHub 开源 (kvcache-ai/Mooncake) | 2024 下半年 | 先开源 Transfer Engine |
| FAST '25 Best Paper | 2025-02 | 同社区第一篇 PD-disagg + KVCache pool 联合方案 |
| Mooncake Store 开源 | 2025-03 | Store 独立项目,与 vLLM xPyD PD-disagg 后端联调 |
| Conductor RFC (#977) | 2025-10 | Conductor 公开化、走 HTTP API、与 SGLang / vLLM 共享 prefix cache |
| ACM TOS 期刊版 | 2025-11 | 增加 Store 生产数据 |
| PyTorch Ecosystem | 2026 初 | 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 function | argmin (transfer + prefill + queue_wait),配 hot-spot replication |
| Prediction-based ER | 预测 decode 是否违反 TBT SLO,提前拒绝避免浪费 prefill |
| 关键数据 | Kimi trace +75%; 16k-128k 长上下文 +50% ~ +525% (vs vLLM 4M) |
参考资料
- 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