第 06 章

服务集群 · 自动扩缩 · 容量 · prefill/decode 分离

从单 replica 到集群:自动扩缩、容量管理,以及为什么把 prefill 和 decode 拆成两套独立 fleet(它们的资源画像互相冲突)。以 DeepSeek-V3 的 EP320 decode 部署作真实顶点案例。前置:Ch5。

约 2.5 小时
把镜头从一台机器拉到整个集群 —— 这一章讲机器之间那一层,以及一个真实的顶点部署

这是系统设计路书的第 6 章,约 2.5 小时,纯 Mode A,是第三站「推理服务」主脊的第三章,也是本站最厚的一章。

上一章的连续批处理、调度、缓存路由,做的都是一台机器(或一组对等副本)内部的事。这一章走到机器之间那一层:一个服务亿级用户的 serving 系统,是由成百上千台机器组成的集群,它带来两类新问题。一类是运营:流量有波峰波谷,集群该怎么自动扩缩、怎么提前规划容量,而 LLM 在这件事上有个别人没有的麻烦。另一类是架构:既然 prefill 和 decode 脾气这么相反,在集群尺度上有一个比上一章更彻底的办法,叫 prefill/decode 分离。读完这一章,你会用一个真实的顶点案例把前五章的概念全串起来:DeepSeek 怎么把上百张卡组织成一个专门的 decode 机群。

本章三节:

  • 从单副本到集群:自动扩缩与容量(35 min)
  • PD 分离:把脾气相反的两段拆到两组机器(40 min)
  • 真实顶点:DeepSeek 的 EP320 decode 机群(45 min)

0. 上一章在机器里,这一章在机器之间

上一章结尾我给了你一个分层,现在正式踏进它的第二层。回顾一下:连续批处理把空槽填满、chunked prefill 让 prefill 和 decode 不互相憋死、缓存感知路由把共享前缀的请求聚到一起,这些招式有一个共同点,它们都发生在一台机器内部,或者一组装着同一份模型、彼此对等的副本之间。但真实的生产 serving 从来不是一台机器,服务亿级用户意味着一个由成百上千台机器组成的集群,而集群这个尺度会冒出一台机器上根本看不见的新问题。

这一章就讲这些新问题,它们分成两类。第一类是运营层面的:用户流量白天高、夜里低,还时不时突发,集群得能跟着增减机器(自动扩缩),也得提前想好留多少机器(容量规划),而你马上会看到,LLM 在这两件事上都比普通 web 服务难办。第二类是架构层面的:前面几章我们一直在跟 prefill 和 decode 这对脾气相反的孪生兄弟较劲,在一台机器里只能用 chunked prefill 这种调度手段调和它们;但到了集群尺度,有一个更彻底、也更漂亮的办法,就是干脆把它们拆到两组不同的机器上去。这一章的最后,我们会看一个把这一切用到极致的真实系统。

1. 从单副本到集群:自动扩缩与容量

先说运营。一个副本能同时服务的请求是有限的,而真实流量是起伏的,所以最自然的想法是自动扩缩:负载高了就多开几个副本,负载低了就关掉几个,既扛得住高峰又不在低谷浪费钱。这套在无状态 web 服务里早就是标准操作,云平台几秒钟就能拉起一个新实例。但把同一套搬到 LLM serving 上,你会立刻撞到一堵别人没有的墙。

这堵墙是冷启动。一个普通 web 服务的新实例,启动起来就是拉一个几十兆的镜像,几秒钟的事;而一个 LLM 副本要先把模型权重装进显存,这些权重动辄几十上百 GB,要从远端存储拉过来再加载,慢的时候是分钟级而不是秒级。公开的工程报告里,启动一个新的大模型实例耗时常在十几分钟这个量级,极端情况下跨区域冷拉权重能到几十分钟。这意味着等你发现负载上来、再去开新副本,十几分钟后它才能干活,黄花菜都凉了。自动扩缩那套「按需秒级伸缩」的前提,在这里基本失效。

既然没法即时扩,工程上的应对就是提前备好余量:常态就多开一些热副本(warm replica)垫着,宁可平时有点闲置,也好过高峰来了抓瞎。代价是真金白银,留越多余量,GPU 的账单就越高,业界的经验是这种 headroom 能让你的 GPU 开销翻上一两倍。所以 LLM serving 的容量规划不是一道「需要时再加机器」的弹性题,而是一道「提前 provision 多少、留多少安全垫」的预算题,这也是为什么前沿实验室会专门设容量治理的岗位。下面这张图把这个滞后画了出来。

时间 →白天高峰蓝阶梯 = 已部署容量,常压在需求之上留 headroom 余量突发时加副本要几分钟,阶梯追不上 → 缺口只能排队 / 降级需求(流量)已部署容量(副本数)
自动扩缩为什么难:LLM 副本冷启动要几分钟(得把几十上百 GB 权重装进显存),没法像无状态 web 服务那样秒级拉起。所以容量(accent 阶梯)平时要留在需求(amber)之上一截余量;可一旦突发,阶梯还是追不上,中间那段缺口只能排队或降级 · 对应正文 第 1 节

而要规划容量,你得先会一件事:估算一个副本到底能扛多少。这里又有一个反直觉的点,容量的真正单位不是每秒多少请求(QPS),而是 KV cache 的显存预算。回想上一章的结论,你能同时拼进一个批的请求数,被显存里还能塞下多少块 KV cache 卡住;那么一个副本的并发上限,本质上就是「权重装完之后,剩下的显存能容纳多少块 KV cache」。举个被反复引用的算法:假设某配置下一张卡的显存正好够装 47 条满长度(8K token)的序列,可如果真实请求平均只有 1000 个 token,那它实际能同时服务的请求数就接近 47 乘以 8 倍、也就是约 385 个。同样一张卡,容量随请求的长度画像浮动,所以做容量永远要回到 KV cache 这本账上,而不是拍一个 QPS 数字。

把这一节收一下:LLM serving 的运营之难,根子都在那块又大又必须常驻显存的东西上。权重大,所以冷启动慢、扩缩不能即时、必须留余量;KV cache 大,所以容量得按显存预算算、而不是按请求数。运营这一层你心里有了底,我们就可以回到那对老朋友 prefill 和 decode,看集群尺度上对付它们那个更彻底的办法。

2. PD 分离:把脾气相反的两段拆到两组机器

这一节回到一个我们已经反复确认的事实:prefill 是算力密集的(compute-bound),decode 是显存带宽密集的(memory-bound),两者脾气相反。上一章在一台机器里,我们用 chunked prefill 把大 prefill 切碎、插进 decode 之间,缓解它们抢资源。但那终究是在一口锅里调和两道脾气不合的菜。到了集群尺度,一个更彻底的想法浮出水面:既然它们这么不合,为什么要塞在同一台机器上?干脆拆开,prefill 用一组机器,decode 用另一组。这就是 prefill/decode 分离(简称 PD 分离)。

拆开的好处,不止是「不互相拖累」这一层。更深的好处有两个。第一,两组机器可以各自选最合适的配置:prefill 那组按算力优化,decode 那组按显存带宽和大批量优化,不必再为了照顾对方而妥协。第二,也是运营上的大杀器,两组可以各自独立扩缩。你的流量画像里,如果 prompt 普遍很长(prefill 压力大),你就多加 prefill 机器;如果对话普遍很长(decode 压力大),你就多加 decode 机器,两边互不牵连。回到上一节的容量难题,这等于把一道耦合的容量题拆成了两道可以分开解的题,灵活得多。

那拆开之后,一次请求怎么走?机制其实很直接:请求先进 prefill 机群,把整段 prompt 算完,产出那块 KV cache;然后这块 KV cache 经过机器之间的高速网络(就是第三章讲的 RDMA / InfiniBand)传到 decode 机群,由 decode 机群接手,逐 token 把回答生成出来。这里有个常见的误解需要破一下:你可能担心「把 KV cache 在机器之间搬来搬去,代价不是很大吗?」实际上传输本身并不贵,走 RDMA 直传、还能和 prefill 的计算重叠着进行,开销小到几乎可以忽略。PD 分离真正需要「足够大规模才划算」的原因不在传输,而在运营:你得有足够的流量,才能把 prefill 和 decode 两个专门的池子各自喂满、都跑在高利用率上,否则拆开反而两头都不饱。下面这张图对比了混在一起和拆开两种布局。

混在一起 collocated · prefill 和 decode 在同一台抢资源PDPDPD每台机器一边算 prompt 一边吐字,两段脾气冲突、互相拖累PD 分离 disaggregated · 两组专门机群,各自优化、各自扩缩Prefill 机群算力密集 · 独立扩缩Decode 机群显存带宽 + 大 batch · 独立扩缩KV cache 经 RDMA 传过去传输走 RDMA 不贵(能和计算重叠);够大规模才能把两组池各自喂满
把脾气相反的两段拆开。混在一起(上):每台机器又做 prefill 又做 decode,二者抢资源、互相拖累(Ch5 的 chunked prefill 是在机器内部缓解它)。PD 分离(下):prefill 放一组算力优化的机群,算完把 KV cache 经 RDMA 传给另一组显存/带宽优化的 decode 机群,两组各用最合适的硬件、各自独立扩缩 · 对应正文 第 2 节

这个想法不是 DeepSeek 发明的,它有清楚的学术源头,也正是你在第一章技术弧 第 1.4 节 见过的那两个名字:微软的 Splitwise(发表在体系结构顶会 ISCA 2024)和 DistServe(北大、UCSD 与 StepFun 合作,发表在 OSDI 2024),它们先后把「按阶段拆分」这件事讲透并验证。到 2025 年,PD 分离已经从论文走成了大规模 serving 的事实标准,英伟达的 Dynamo、开源的 llm-d 都把它做成了开箱即用的能力。可以说,这是 2026 年 serving 架构上最重要的一次范式转变,而它的全部出发点,就是 prefill 和 decode 那对从第四章纠缠到现在的相反脾气。

3. 真实顶点:DeepSeek 的 EP320 decode 机群

抽象的 PD 分离讲完了,该看一个把它用到极致的真实系统。我们选 DeepSeek-V3,因为它是当前披露得最完整的顶点部署 —— 技术报告里专门有一节(第 3.4 节)把推理系统的真实配置摊开给所有人看。先说清楚时间坐标:这是 2024 年底的部署,前沿其后已经走到了 V4,但原理完全相同,只是数字更大,所以它至今仍是最好的教学样本。

DeepSeek 把 prefill 和 decode 彻底拆成了两套部署,而两套的规模差出一个量级。prefill 那套的最小部署单元是 4 个节点、32 张 H800,用 32 路专家并行(EP32)。decode 那套则是 40 个节点、320 张卡,用 320 路专家并行(EP320)。先停下来体会一下这个对比:服务同一个模型,decode 机群的规模是 prefill 的整整十倍。这本身就是 PD 分离威力的最好证明 —— 因为两阶段被拆开了,DeepSeek 才能根据各自的真实压力,把资源极度不对称地分配下去,而这在混在一起的布局里是做不到的。下面这张图按真实的节点数比例把两套画了出来。

DeepSeek-V3 第 3.4 节:prefill 与 decode 拆两套,decode 用 320 路专家并行Prefill 机群4 节点 · 32 GPUEP32KV cache 经 RDMADecode 机群(10× 大)40 节点 · 320 GPUEP320≈ 64 GPU(8 节点)放冗余 / 共享专家 · EPLB 动态均衡热门专家1 格 = 1 节点(8 GPU)
DeepSeek-V3 技术报告 第 3.4 节 的真实部署(2024):prefill 与 decode 彻底拆开,decode 用 320 路专家并行(40 节点)把每个 token 路由到散在 320 个 GPU 上的专家;约 64 个 GPU(amber)专门放冗余/共享专家,由 EPLB 动态均衡热门专家。这是报告里的数字 —— 实际生产系统跑过更小的 EP144,前沿其后已到 V4(原理相同、数字更大)· 对应正文 第 3 节

那么问题来了:decode 为什么需要 320 路专家并行这么夸张的规模?答案要接回第三章。DeepSeek-V3 是个 MoE 模型,每个 token 在生成时只激活一小部分专家,而这些专家被分散部署在那 320 张卡上;于是 decode 每生成一个 token,都要把它路由到它该去的专家所在的卡,这正是第三章讲的那次 all-to-all 通信。专家越多、摊得越开,单卡要装的专家就越少、显存压力越小,但代价是路由的通信越复杂。EP320 就是把这个权衡推到了一个极致的规模。

可一旦专家摊到这么多卡上,一个新麻烦冒出来了:MoE 的路由是不均匀的,有些专家是热门的,大量 token 都往它那儿挤,而冷门专家门可罗雀。如果热门专家恰好独占一张卡,那张卡就会被挤爆、成为整个 all-to-all 步骤里最慢的那个,把所有其他卡都拖着干等。DeepSeek 的解法叫冗余专家:把高负载的热门专家复制好几份、部署到多张卡上,分摊它的压力。在它的 decode 部署里,有大约 64 张卡专门用来放这些冗余专家和共享专家。而决定「哪些专家该复制、复制几份、放在哪张卡」的,是一套叫 EPLB(专家并行负载均衡器)的系统,DeepSeek 在 2025 年的开源周里把它开源了出来,它会根据估算出的专家负载,动态算出一套复制和放置方案,把热门专家均摊开。

讲到这,你应该能感觉到这个 decode 机群的分量:它是这条路书前五章概念的一个总汇合点。它站在 PD 分离(本章)之上,内部跑着专家并行的 all-to-all 通信(第三章),每张卡的容量被 KV cache 的显存预算卡着(第四章),而 EPLB 做的负载均衡正是上一章那个路由思想在专家这一层的放大版。一个 EP320 的 decode 机群,就是「把一个大型 MoE 模型服务到生产规模」在 2024 年的样子。

最后补两句诚实话,免得你把这些数字当成铁律。第一,报告里的数字和实际生产跑的并不完全一样:上面那套 40 节点 EP320 是技术报告里描述的配置,而 DeepSeek 在 2025 年开源周公布的实际推理系统,decode 跑的是一个更小的 EP144。报告给你看的是设计的上限,生产跑的是当下最划算的点,两者都对、都值得你知道,这也提醒你读任何系统报告时都要分清「论文里的」和「真跑的」。第二,这是 2024 年的部署,而 DeepSeek 在 2026 年的 V4 里已经做了关键改动,比如把 V3 那个「每个 token 最多只路由到 4 个节点」的约束整个移除了 —— 这又是一次第一章讲的撞墙开新轴:V3 用约束绕开通信墙,V4 用更聪明的方案让约束不再必要。具体数字会一直变,但「prefill/decode 拆开、按真实压力不对称分配、再用负载均衡治理专家」这套设计逻辑,会比任何一个具体数字活得更久。

综合 · 你现在能看懂一个 serving 集群了

把这一章收拢。你先看清了集群运营的两个 LLM 特有难处:权重太大,所以副本冷启动慢、自动扩缩不能即时、必须预留 warm headroom;KV cache 太大,所以容量的单位是显存预算而不是 QPS。接着你拿到了集群架构上最重要的那一招 —— PD 分离:把脾气相反的 prefill 和 decode 拆到两组专门的机器,各用最合适的硬件、各自独立扩缩,中间用 RDMA 高速传 KV cache(传输不贵,够规模才划算是为了喂满两个池)。最后你用 DeepSeek 的 EP320 decode 机群把这一切落了地,也看到了冗余专家和 EPLB 怎么治理大规模专家并行的负载不均。

这三件事其实指向同一个更高的判断:到了集群尺度,你设计的不再是「一台机器多快」,而是「一堆专门化的机器怎么各司其职、各自伸缩、协同起来」。而拉动这些设计决策的,始终是那组从第一章就立下的旋钮 —— 延迟、吞吐、成本、可靠性。PD 分离让你能分别为延迟(decode 的 TBT)和吞吐(prefill 的批量)去优化不同的池;容量规划是在成本和「扛不扛得住高峰」之间定平衡;而冗余专家是在多花一点显存和「别让单卡拖垮整步」之间做交换。看一个 serving 集群的设计,你现在能一眼看出它在这几个旋钮之间站在哪。

学完这一章,你已经能推理一个生产 serving 集群的运营面(怎么扩缩、怎么估容量),能解释 PD 分离为什么是大规模 serving 的范式,也能读懂 DeepSeek EP320 这类真实顶点部署在做什么。第三站的概念到这里基本铺齐了。下一章 Ch7 不再讲新概念,而是带你走进一个真实的开源 serving 系统 vLLM 的源码,把第四到第六章学的这些抽象 —— KV cache、连续批处理、调度、分页 —— 一个个在真实代码里对号入座,看它们到底长成什么样。这是你把「懂概念」变成「能读真实系统」的关键一步。

本章关键术语

本章引入的 canonical 术语,点进术语表看更完整的解释:

  • PD 分离 prefill/decode disaggregation 把推理两阶段拆到两组专门机器:prefill 机群算完 prompt、产出 KV cache,经 RDMA 传给 decode 机群逐 token 生成;两组各选硬件、各自独立扩缩。源头 Splitwise(ISCA'24)/ DistServe(OSDI'24)
  • 冗余专家 redundant experts MoE 专家并行里把热门专家复制到多卡,避免持有热门专家的卡成为 all-to-all 的 straggler;配套 EPLB(DeepSeek 2025 开源)按估计负载动态算复制+放置方案
  • 自动扩缩 autoscaling 按负载增减副本数;LLM 的特殊难处是冷启动以分钟计(装几十上百 GB 权重),撑不进一个扩缩周期 → 要预留 warm headroom;容量单位是 KV cache 显存预算而非 QPS

参考文献

Mode A · 引用出处(正文 inline,集中列在此)

深 dive 资源(可选 · 想往下走再看)

说明:本章同样没有 Mode B 视频站 —— 大规模 serving 集群这类硬核系统主题缺少合格的人讲解长视频;深入的会议论文(ISCA / OSDI)、DeepSeek 的真实开源资料与引擎文档由 Mode A 原创讲解串起。

下一章

下一章 Ch7 是第三站的收官,也是一次换挡:前面四章(Ch4 到 Ch6)我们建立了一整套 serving 的概念 —— prefill 与 decode、KV cache、连续批处理、调度、PD 分离。Ch7 不再添新概念,而是带你走进开源推理引擎 vLLM 的真实源码,把这些抽象在一行行代码里对号入座:PagedAttention 怎么像操作系统管虚拟内存那样管 KV cache、调度器长什么样、KV cache manager 怎么实现。你会学到一套读真实 serving 系统源码的方法,把「懂这些概念」真正变成「能读懂跑在生产里的那套系统」。