前缀缓存 Prefix Caching

Prefix Caching / Prompt Prefix Sharing

前缀缓存是把多个不同请求之间相同的 System Prompt / Tool Schema / 长文档上下文这类公共前缀的 KV Cache 预先算好持久化缓存,后续请求直接复用而不再重复计算,能让长 System Prompt 场景下的 TTFT 和总 Token 成本下降 30% 至 80%。

详细解释

**Prefix Caching(前缀缓存 / Prompt Prefix Sharing,简称 Prefix Cache)**一句话:你所有的请求都有同一个长 System Prompt(1000 Token,包括人设、工具定义 JSON、安全规则、公司政策这些),100 个不同用户提问都要把这 1000 个 Token 的 Prefill 阶段 KV Cache 重新算一遍,浪费了 90% 的 Prefill 算力;前缀缓存就是把这 1000 个公共前缀 Token 的 KV Cache 预先算好、存在内存里(甚至写到磁盘持久化),给它一个固定的 cache_key,任何请求只要说「我用 cache_key=xxx 的前缀」,推理引擎就直接把这 1000 个 Token 的 KV Cache 从缓存里拿过来用,不再重新算 Prefill。在 Agent 多工具调用、长 System Prompt + 工具定义的真实业务场景下,TTFT(首字延迟)能直接下降 50-80%,GPU 算力省 30-60%,是 2024-2025 年推理成本优化的第一利器。

前缀缓存的两种实现层级:(1)Request-level Prefix Sharing(请求内前缀共享,vLLM PagedAttention 原生支持)——同一个推理 Batch 里多个请求如果前缀 Token 序列完全相同,直接共享同一份 KV Cache 物理页,Batch 内 10 个请求共享同一 System Prompt,Prefill 算力降为原来的 1/10;(2)Cross-request Persistent Prefix Cache(跨请求持久化,SGLang RadixAttention、TensorRT-LLM 支持)——不仅同 Batch 里共享,把最常用的 10-100 个前缀(比如你的默认 System Prompt + 默认工具定义 + 常用的长文档)的 KV Cache 存在一个全局的 LRU + 持久化 Cache 池,跨分钟、跨小时、跨天复用,用 cache_key 去索引,命中率能到 60-95%。第二种比第一种在真实在线业务上省得更多(因为大部分请求跨 Batch 分布)。

唯元智创 的兼容 API 对所有企业客户默认打开前缀缓存:客户第一次调用时如果传 extra_body.prefix_key="你的业务专用key" 并且带上完整前缀,系统就把这份前缀的 KV Cache 持久化下来;后续所有请求只要传同一个 prefix_key 就不用再传前缀内容,TTFT 平均下降 70%,一个月下来企业客户平均能省 40% 的 Token 费用和 60% 的 GPU 推理算力。

两代前缀缓存架构对比(2025 年选型)

维度vLLM PagedAttention 级别 Request-level 前缀共享SGLang / TRT-LLM Persistent Radix Cache 跨请求持久化前缀缓存
核心数据结构物理 KV Cache 页 + 页表共享前缀页前缀 Trie 树(Radix Tree)索引 + KV Cache 页
共享范围同一个推理 Batch 内部的请求跨所有请求(跨 Batch、跨分钟、跨小时)
典型命中率20%–40%(取决于 Batch 大小和前缀相似度)60%–95%(取决于是否常用前缀集中)
TTFT 下降比例Batch 内共享时 30–50%命中持久缓存时下降 70–90%
是否需要代码改动不用,传相同前缀 Token 即可自动匹配需要传 prefix_uid 或用前缀哈希做键,SGLang 支持自动哈希匹配
KV Cache 内存占用没额外开销(页共享不新增内存)额外占 GPU HBM 5-20% 存热点前缀池
GPU 算力节省20–40%40–70%
推荐度⭐⭐⭐⭐ 所有部署 vLLM 的系统默认就能享受到⭐⭐⭐⭐⭐ 高流量生产服务首选,SGLang 2025 默认开启

落地前缀缓存的 5 条最佳实践

  1. 优先把 System Prompt + 工具定义(Function Calling Schema)做成独立前缀缓存——这是所有请求 100% 相同的部分,用一个固定的 cache_key;实测这一个前缀就能覆盖 50-70% 的 Prefill Token。
  2. RAG 场景下,把常用的文档 Chunk 也做成前缀缓存——比如你有一个 10 万字的产品手册每天有几千人问关于它的问题,把产品手册全文(切到合适长度)的 KV Cache 做好缓存,每次用户问产品相关问题时先 load 这个缓存前缀,再追加用户问题,Prefill 只算用户问题 + RAG 最新召回的 3-5 条额外 chunk,Prefill 算力下降 80%。
  3. 前缀一旦写入缓存,修改就要换版本号 / 换 cache_key——千万不要修改已缓存前缀的内容还复用旧 cache_key,前缀内容变了 KV Cache 完全不兼容,会导致模型输出严重错乱(相当于给它灌了错的上下文);正确做法是用前缀哈希或版本号 v1/v2/v3 做 cache_key,内容改了就升版本,旧版本保留 7 天 TTL 自动过期。
  4. 前缀 Cache 做两级缓存(GPU HBM LRU + CPU 内存 / 磁盘持久化)——常用热门前缀放在 GPU HBM LRU 里(容量 10-50 条,毫秒级命中),温前缀放在 CPU 内存(容量 100-1000 条,几十毫秒加载到 GPU),冷前缀写到本地 NVMe(容量上万条,几百毫秒加载),分层命中率最高、成本最低。SGLang 2025 版原生支持三级分层前缀缓存。
  5. 做前缀 Cache 命中率监控 + 冷启动预热——上线后盯三个指标:命中率(目标 ≥ 70%)、命中延迟(目标 < 5ms)、未命中的 Prefill 额外计算时间;冷启动时把 Top 20 热门前缀先加载到 GPU HBM,用户第一个请求就能 100% 命中,不要等用户请求触发被动加载。

常见问题

前缀缓存和普通 Prompt Caching(之前写的 prompt-caching)有什么关系?是同一个东西吗?
强相关但不是同一层面——Prompt Caching(提示缓存)是 OpenAI/Anthropic/唯元智创 等 API 平台对终端客户的「计费层优化」:相同前缀的 Token 按 50-90% 的折扣计费(因为平台内部用 Prefix Cache 省了算力,把一部分省下来的钱让利给你);而 Prefix Caching(本文前缀缓存)是底层推理引擎(vLLM/SGLang/TRT-LLM)实现 Prompt Caching 计费的技术手段两者的关系可以类比:你买机票的「折扣票价」(Prompt Caching 计费折扣)和航司用的「代码共享/联程优化」(Prefix Cache 技术实现)——前者是你作为用户能拿到的对外优惠,后者是航司内部实现折扣还能赚钱的底层技术方法。实际使用中,如果你调用第三方兼容 API,只需要关心 API 层的 Prompt Caching 命中率和省钱比例,不需要关心底层推理引擎用的是哪一种 Prefix Cache;如果你是自己私有化部署模型对外提供 API 服务,那你需要自己在推理引擎层实现 Prefix Cache,之后才能在 API 层对客户做 Prompt Caching 的计费折扣——两者是「上下层」的关系,不是非此即彼。
前缀缓存会不会和 KV Cache 淘汰策略冲突?高并发下热门前缀会不会被挤掉?
会冲突——这是只开默认 LRU 前缀缓存的大坑,2024 年很多团队踩过:你的热门前缀(比如默认 System Prompt)占了 1 万个 KV Cache 页,但某一分钟突然来了一波 Batch 很大的请求,LRU 策略会把最近最少用的页先淘汰,热门前缀刚好这 1 分钟没访问就被挤掉,下次再命中时又要重新花 500ms Prefill 重新算一遍,TTFT 抖一下用户能明显感觉卡。解法三条:(1)把「永久前缀」(固定 System Prompt、工具定义)钉在 GPU HBM 里不走 LRU 淘汰——SGLang 叫 Pinned KV Cache,vLLM 可以通过给前缀页加 pin 标记实现,这部分页永远不被淘汰;(2)GPU HBM 分分区:20% 专门放 Pinned 前缀、60% 放 LRU 温前缀、20% 留给当前请求的动态 KV Cache,互不抢资源;(3)做「最近 1 小时命中数 ≥ N」的自动升 Pin 策略——当某前缀连续 1 小时命中超过 1000 次,自动把它从 LRU 升级到 Pinned 区,冷前缀(偶尔用一次)永远在 LRU 里不会占 Pinned 资源。这样热门前缀被挤掉的概率从 30% 降到 < 0.1%,TTFT 抖动基本消失。KV Cache Eviction 里关于分层分区策略的内容也适用于这里,直接照搬。
多卡 Tensor 并行 / Pipeline 并行场景下前缀缓存怎么同步?每张卡各存一份还是共享?
张量并行(Tensor Parallel, TP)场景下:每张卡存自己那一份前缀的分片 KV Cache(因为 TP 时 Attention 的 K/V 按头分片在不同卡),所以同一份前缀在 8 卡 TP 时会存 8 份分片,加载时 8 张卡同步从各自的前缀缓存里取,必须保证 8 卡的 cache_key 和前缀版本号完全一致,不一致会导致 Attention 拼起来完全错乱。Pipeline 并行(PP)场景下:每个 Stage(层范围)存对应层范围的前缀 KV Cache,Stage 0 存 1-8 层、Stage 1 存 9-16 层、Stage N-1 存最后 8 层,各存各的、各取各的,通过同一份全局 cache_key 作为纽带串起来。同步和一致性注意三点:(1)写前缀时一定用「两阶段提交」——所有卡/Stage 写成功了再对外宣告 cache_key 可用,任何一张卡写失败全部回滚删除,禁止出现 7 张卡写了第 8 张没写的中间态;(2)所有卡/Stage 的前缀版本号必须全局一致,读之前先比对版本号,任何一个不匹配都当作未命中,重新统一 Prefill;(3)跨节点/跨机集群时,把前缀缓存放在节点本地 NVMe 上 + 全局 Redis 存元数据(cache_key 对应哪些节点已写好),不要走网络共享盘(PCIe/NVMe-oF 网络加载的延迟是本地的 100 倍)。70B 以上的大模型多卡部署前缀缓存基本都是 TP8 / PP2 × 2 机这种架构,按上面三条做基本不会出一致性问题。