缓存命中:AI 推理中最被低估的指标
你的 LLM API 账单里可能藏着 70% 的水分——一切都取决于这三个字:命中率
引言:一个被忽略的杠杆
当你把 system prompt 从 3,000 token 优化到 500 token,你很高兴。当你切换到更便宜的模型,你更高兴。
但你可能从来没问过一个问题:我的缓存命中率是多少?
2025-2026 年,AI 推理缓存已经不再是「可选的优化」,而是架构的核心支柱。OpenAI、Anthropic、Google 都内置了自动缓存,vLLM 和 SGLang 把 KV Cache 命中率做到了 95%+。然而,大多数团队根本没意识到自己正在为重复的计算付两次钱——而且是全价。
这篇文章不聊缓存技术原理,我们只聚焦一个数字:Cache Hit Rate(缓存命中率)——它是什么、怎么算、什么影响它、如何优化、以及它到底值多少钱。
前传:缓存是什么?AI 缓存跟一般缓存有何不同?
缓存是什么
缓存(Cache)是计算机科学最古老的优化手段之一:把昂贵操作的结果存下来,下次需要时直接复用。
- CPU 有 L1/L2/L3 缓存——避免每次都去内存读数据
- 数据库有 Buffer Pool——避免每次都去磁盘读数据
- CDN 有边缘缓存——避免每次都回源站拉文件
- 浏览器有 HTTP 缓存——避免每次都重新下载资源
它们的共同逻辑:空间换时间。花一点存储空间,换取大量重复计算或 I/O 的节省。
AI 缓存的独特之处
AI 模型推理的缓存,和传统缓存有本质差异:
1. 缓存粒度:从「文件」到「数学状态」
传统缓存缓存的是完整的结果——一个 HTML 页面、一张图片、一条 SQL 查询结果。命中了就直接返回,不存在「部分命中」的概念。
AI 缓存缓存的是计算的中间状态——Key-Value 矩阵。一个 prompt 可能有 8,000 token,缓存命中了前 6,000,剩下 2,000 仍然需要计算。这意味着:
- 命中率不是 0 或 100%,而是一个连续的百分比
- 80% 的命中率表示 80% 的 token 被缓存覆盖,只需计算剩下的 20%
- 这带来了潜在地累计算错误的可能:命中率 60% 的请求比 50% 的便宜一些,但差距只是 10 个百分点的 prefill 量
2. 缓存键:从「精确 Key」到「前缀匹配」
传统缓存用精确 Key来索引——URL、SQL hash、文件名。Key 不对,就是 miss。
AI 缓存用前缀匹配——新请求的 prompt 开头和缓存中的某个 prompt 开头一致,就是 hit。这意味着:
- 缓存命中判断本身就是一个计算操作(字符串/向量匹配)
- 两个请求不必完全相等,共享一部分前缀就能获益
- 同一个缓存条目同时服务无数个不同的请求(只要它们的前缀相同)
3. 一致性模型:从「强一致」到「近似一致」
传统缓存要求命中返回的结果必须与重新计算结果完全一致。返回过期数据是 bug。
AI 缓存面临不同的权衡:
- KV Cache 缓存的中间状态在数学上保证与重新计算完全一致
- Semantic Cache(语义缓存)则允许一定程度的近似——两个语义相似的 prompt 共享同一个回答,可能丢失细微差异
- GenCache(生成式缓存)更进一步:缓存的不再是结果,而是生成结果的模式,用程序动态合成适应变化的新回答——这已经完全不是传统意义上的「缓存」了
4. 成本结构:从「省存储」到「省计算费」
传统缓存节省的是 I/O 和带宽成本。一个 CDN 命中 = 省了回源的服务器 CPU + 带宽。
AI 缓存节省的是 GPU 计算成本,这是目前最昂贵的计算资源之一:
- 一次 GPT-4 级别的 prefill,100K token 的 prefill 可能需要数秒的 GPU 时间
- 缓存命中后,这部分 GPU 时间归零
- API 层面的缓存折扣高达 90%(Anthropic)或 75-90%(OpenAI,GPT-4.1 为 75%,GPT-5 系列为 90%)
- 在 AI 场景,缓存直接等于真金白银
5. 时效性与写成本
传统缓存没有「写成本」的概念——为了给将来的命中做准备,缓存写入本身几乎免费。
AI 缓存的写入是有真实成本的:当你第一次发送一个 prompt,API 提供商会完整计算一遍 prefill,然后把中间结果(KV Cache)存起来。这个计算过程你付了 100% 的费。对于 Anthropic 而言,你还要额外付 25% 的「写溢价」——因为它消耗了服务端宝贵的 GPU 显存来保存你的缓存条目。
| 维度 | 传统缓存 | AI 缓存 |
|---|---|---|
| 缓存内容 | 完整结果(HTML、图片、数据) | 计算中间状态(KV 矩阵) |
| 索引方式 | 精确 Key 匹配 | 前缀匹配 |
| 命中粒度 | 二值(hit/miss) | 连续百分比 |
| 一致性 | 强一致(过期=bug) | 可接受部分近似 |
| 成本节省 | I/O + 带宽 | GPU 计算(最贵的资源) |
| 写入成本 | 几乎为零 | 25-100% 的额外费用 |
| 缓存体量 | KB ~ MB | MB ~ GB(单请求可能数 GB) |
这就是 AI 缓存如此独特的原因:它面对的「昂贵操作」比传统场景贵几个数量级,但缓存本身的代价也同样高昂。命中率不仅是性能指标,更是财务指标。

第一章:命中率是什么?怎么算?
定义
AI 模型推理中有两层缓存,命中率的定义也不同:
1. Prompt Cache 命中率(API 层)
命中率 = 命中缓存的 token 数 / 总输入 token 数
当你调用 OpenAI 或 Anthropic 的 API,如果 prompt 前缀和之前的请求相同,API 服务端会跳过重复的 prefill 计算,直接读取缓存结果。这部分 token 享受折扣价。
- 每次响应都会返回
usage.cached_tokens字段 - 如果 0,说明完全没有命中的 token
2. KV Cache 命中率(引擎层)
命中率 = 缓存中匹配的 token 数 / 总预填充 token 数
在 vLLM、SGLang 等推理引擎内部,这衡量的是:新请求能在已有缓存中找到多少个匹配的前缀 token。命中越多,需要从头计算的 prefill 越少。
基线数据
不同场景下的典型命中率差异巨大:
| 场景 | 典型命中率 | 说明 |
|---|---|---|
| 多轮对话(活跃 session) | 80-95% | 对话历史几乎不变,前缀稳定 |
| RAG 流水线 | 70-90% | 大量共享的文档 chunk + 固定指令 |
| Few-shot 推理 | 60-80% | 示例部分可缓存 |
| Agent 工作流(工具定义) | 50-85% | 系统 prompt + 工具 schema 不变 |
| 随机多样化查询 | 20-40% | 前缀变化大,命中困难 |
| 一次性任务 | <5% | 几乎没有机会命中 |
第二章:命中率的真实经济学
API 层:Prompt Cache 的算账
这是最直观也最容易算清楚的部分。2025-2026 年主流平台的定价模型:
Anthropic(Claude Sonnet 4.6 为例)
| 操作 | 单价 | 相对于基础价 |
|---|---|---|
| 基础输入 | $3.00/M tokens | 1.00× |
| Cache 写入(首次) | $3.75/M tokens | 1.25× |
| Cache 命中 | $0.30/M tokens | 0.10× |
OpenAI(GPT-4.1)
| 操作 | 单价 | 相对于基础价 |
|---|---|---|
| 基础输入 | $2.00/M tokens | 1.00× |
| Cache 命中 | $0.50/M tokens | 0.25× |
| Cache 写入 | 无额外费用 | 1.00× |
📝 2026-10-12 更新:GPT-5 系列的缓存命中价已降到基础价的 0.10×(如 GPT-5.4:输入 $2.50/M,缓存命中 $0.25/M),同样不收写入费。来源:OpenAI 价格页。
注意关键差异:Anthropic 命中后打 90% 折扣(0.10×),但首次写入要付 25% 溢价(1.25×)。OpenAI 命中后打 75-90% 折扣(视模型而定),但不收写入溢价。
盈亏平衡点
这是最容易被忽略的陷阱。Anthropic 缓存写入要付 25% 的溢价,意味着:
你需要至少约 1.4 次命中才能收回写入成本。
计算过程:
- 写入成本:8K tokens × $3.75/M = $0.030
- 每次命中节省:8K tokens × ($3.00 - $0.30)/M = $0.0216
- 盈亏平衡:$0.030 / $0.0216 ≈ 1.39 次命中
也就是说:如果同一个缓存前缀在 5 分钟 TTL 窗口内(Anthropic 默认缓存时间为 5 分钟)只被请求了 1-2 次,你可能还不如不开缓存——因为写一次亏一次。
OpenAI 则不同
由于 OpenAI 不收写入溢价,每次命中都是纯省:
- 命中 1 次 → 节省 50%
- 命中 0 次 → 不亏不赚
所以 OpenAI 的缓存几乎永远是净收益,只是收益大小取决于命中率。
真实账单对比
场景:一个客服 Agent,每天 200 个 session,每个 session 5 轮对话。
设定:
- System prompt + tool definitions = 8K tokens(每轮不变)
- 用户输入(每轮不同)= 2K tokens
- 每轮 API 调用:system prompt(8K)+ 用户输入(2K)
不缓存(每轮全价付 10K tokens):
每 session:5 轮 × 10K = 50K tokens
每天:200 × 50K = 10M tokens
每月(26 个有效天):260M tokens
成本(Anthropic $3/M):260M × $3/M = $780/月
Anthropic 缓存(system prompt 命中):
每 session:
第一轮:写入 8K → $3.75/M × 8K = $0.030
用户输入 2K → $3.00/M × 2K = $0.006
小计:$0.036
第 2-5 轮:命中 8K → $0.30/M × 8K/轮 × 4轮 = $0.0096
用户输入 2K → $3.00/M × 2K × 4 = $0.024
小计:$0.0336
每 session 合计:$0.0696
每天 200 session:$0.0696 × 200 = $13.92
每月(26天):$13.92 × 26 = $362
节省:$780 → $362,约 54%。
如果使用 OpenAI(50% 缓存折扣,无写溢价):
每 session 成本略高(折扣较小),但无写溢价风险。
命中率 > 40% 即可净收益。
关键洞察是:缓存节省的幅度取决于稳定前缀占总输入的比例。本例中 8K/10K = 80% 的 token 是稳定的—这部分享受 90% 折扣。如果 system prompt 只有 2K 而用户输入占 8K,即使 100% 命中,节省也有限。
实际案例研究
🎯 案例 1:一个安全工具公司将动态内容(时间戳、请求 ID)放在 system prompt 前面,命中率只有 7.4%。把稳定内容移到前缀后,命中率飙升至 84%。仅仅一个结构变动,没有改任何业务逻辑。
🎯 案例 2:某 AI 代码助手在 OpenAI 上启用 prompt_cache_key 后,命中率从 60% 提升到 87%。这个参数让请求更可能路由到同一台缓存了前缀的推理引擎。
🎯 案例 3:Culprit(事故分析工具)在 Anthropic 上利用 prompt caching,每轮 RCA 调用成本从 $0.0065 降到 $0.0033——降幅约 50%。加上 Batch API 的 50% 折扣后,边际成本几乎可以忽略。
第三章:影响命中率的六大因素
1. 前缀稳定性
命中率的天花板由你的 prompt 结构决定。
❌ 差:system_prompt + 用户 ID + 时间戳 + 功能描述
✅ 好:system_prompt + 功能描述 + 用户 ID + 时间戳
核心原则:把稳定内容放前面,动态内容放后面。
2. 最小缓存长度
- OpenAI / Anthropic 要求 ≥ 1024 token 才能触发缓存
- Gemini 要求 ≥ 32K token
如果你的 system prompt 只有 500 token,缓存永远不会被触发。永远 0 命中率。
有趣的是:把 prompt 变长反而可能更省钱。一个 900 token 的 prompt 永远不会命中缓存,但加上一个 200 token 的 stable prefix 变成 1,100 token 后,如果命中率 50%,整体成本反而更低。
3. 请求密度
缓存是有 TTL 的:
- OpenAI:5-10 分钟
- Anthropic(默认):5 分钟
- Anthropic(延长):1 小时
- Gemini:用户自定义
如果两个相同前缀的请求相隔 10 分钟以上,Anthropic 的 5 分钟 TTL 已经过期,第二次请求需要重新写入(又付一次 25% 溢价)。
高密度流量是缓存的朋友,低密度流量是缓存的敌人。
4. 路由亲和性
OpenAI 内部根据 prompt 前 ~256 token 做哈希路由。没有路由亲和性,相同前缀的请求可能打到不同的推理实例上,导致缓存 miss。
prompt_cache_key 参数可以增强路由亲和性,让相同前缀的请求更可能到达同一实例。但要注意:每个 prefix + cache_key 组合超过 ~15 RPM 时会溢出到其他实例。
5. 调度策略(引擎层)
在自部署推理引擎中,请求到达的顺序直接影响 KV Cache 命中率:
- 不感知缓存的调度:按 FCFS 处理请求,频繁切换不同前缀
- 缓存感知调度(如 SGLang 的 LPM、PRISM 的 QAS):按前缀相似度分组,先处理能命中缓存的请求
PRISM(2026)的调度-缓存协同设计表明,联合优化调度和缓存驱逐策略可以将命中率提升 5.9-12.2 个百分点。
6. 驱逐策略
当缓存空间不足时,哪些被踢出去直接决定未来命中率:
| 策略 | 核心思路 | 命中率表现 |
|---|---|---|
| LRU(最近最少使用) | 默认选择,踢最久未访问的 | 均衡,对 burst 场景好 |
| LFU(最不频繁使用) | 踢访问次数最少的 | 对长 session 好,但可能有 stale 问题 |
| FIFO(先进先出) | 踢最先缓存的 | 简单但次优 |
| UniCache(2026) | 联合捕捉 session 复用和结构复用 | 比 LRU 好 3.86%-17.32% |
| RAC(2026) | 基于语义关系的驱逐 | 比强基线好 20-30% |
其中 UniCache 的关键洞察是:没有一种驱逐策略在所有负载下最优。混合负载下,LRU、LFU、FIFO 各有所长,UniCache 能动态适配。
第四章:如何在生产环境提升命中率
4.1 Prompt 结构优化(最简单、最高回报)
第一步:审计你的 prompt
// 每次调用时检查
{
"usage": {
"prompt_tokens": 4500,
"cached_tokens": 0 // 如果一直是 0,预警!
}
}
第二步:分离稳定和动态部分
❌ 当前结构(命中率 < 10%):
时间戳 + 用户ID + system prompt + 检索文档 + 用户问题
✅ 优化后结构(命中率 70-85%):
system prompt + 工具定义 + 检索文档 + 时间戳 + 用户ID + 用户问题
第三步:对 OpenAI 使用 prompt_cache_key
# 为所有共享同一 system prompt 的请求设置相同的 key
response = client.responses.create(
model="gpt-4.1",
input=[...],
prompt_cache_key="my-app-v1-system-prompt" # ✨ 关键参数
)
第四步:对 Anthropic 显式标注缓存边界
# 缓存 system prompt 和工具定义
response = client.messages.create(
model="claude-sonnet-4-20250514",
system=[
{
"type": "text",
"text": SYSTEM_PROMPT,
"cache_control": {"type": "ephemeral"} # 🎯 标记缓存
}
],
messages=[{"role": "user", "content": user_input}]
)
4.2 引擎层优化(自部署场景)
选择 RadixAttention(SGLang)而不是 PagedAttention(vLLM)
SGLang 的 RadixAttention 基于 token 级 radix tree,自动发现和复用任意长度的共享前缀。vLLM 的 PagedAttention 基于 block 级匹配——如果共享前缀与 block 边界不对齐,最后几个 token 会被重新计算。
基准测试:
| 场景 | vLLM 命中率 | SGLang 命中率 | 优势 |
|---|---|---|---|
| 多轮对话 | 70-80% | 90-95% | SGLang 强 |
| RAG 流水线 | 60-75% | 80-92% | SGLang 强 |
| 随机查询 | 20-30% | 20-30% | 持平 |
共享前缀比例 > 40% 时,切换到 SGLang 可降低 30-40% 的预填充延迟。
启用缓存感知调度
在 SGLang 中设置 --schedule-policy lpm,优先处理能与现有缓存匹配的请求。在 PRISM 中启用查询感知调度器(QAS),跟踪可复用 segment 的优先级。
调整驱逐策略
基于你的负载特征选择驱逐策略:
- 多轮对话为主 → LRU
- 长期 session + 频繁复用 → LFU
- 混合负载 → UniCache 或 SGLang 的 priority-based eviction
4.3 监控与指标

你需要追踪的不只是命中率,而是收益归因:
命中收益 = 命中 token 数 × (基础价 - 缓存命中价)
写入成本 = 写入 token 数 × 写入溢价
净收益 = 命中收益 - 写入成本
有效命中率 = 净收益 > 0 的会话比例
生产中的预警阈值:
| 指标 | 健康 | 警告 | 危险 |
|---|---|---|---|
| Prompt Cache 命中率 | > 60% | 30-60% | < 30% |
| KV Cache 命中率 | > 70% | 40-70% | < 40% |
| 缓存止损比 | > 2:1 | 1:1 ~ 2:1 | < 1:1 |
必做的监控工具:
- 每次 API 调用记录
cached_tokens字段 - 按最常 miss 的 prompt 模式排序分析
- 定期检查「写入命中比」——如果写入太多命中太少,调 TTL 或改策略
第五章:2026 年的前沿探索
随机化驱逐:RLT
2026 年的一项研究表明,随机化驱逐策略在某些动态负载下比 LRU 好 6.92 倍。直觉:LRU 面对「恶意」或高波动的到达模式时,缓存被反复冲刷。随机化牺牲了确定性,换来了对任意模式的理论下界保证。
结合学习式路由(LBGR),端到端延迟降低 11.96 倍,命中率提升 36.45%。
PRISM:调度与缓存协同设计
PRISM 的核心洞察:调度和缓存是同一枚硬币的两面。
- 调度的决策(先处理哪个请求)直接影响未来缓存的 content
- 缓存驱逐的决策(踢谁出去)反过来影响调度的选择空间
PRISM 的查询感知调度器(QAS)会把共享前缀的请求聚合成”hot lane”优先处理,同时保留冷 lane 的空位避免饥饿。需求感知 radix tree(DART)利用调度器的提示来保护高价值的前缀不被驱逐。
结果:P99 TTFT 降低 23-37%,命中率提升 5.9-12.2 个百分点(绝对值)。
上下文截断与命中率陷阱
一个来自生产环境的反直觉发现:截断上下文会大幅降低命中率。
某企业使用滑动窗口处理超长上下文,将输入截断到只保留最新 token。结果,前缀缓存命中率从 85% 暴跌到 45%,因为截断后的输入不再匹配已缓存的完整前缀。
教训:如果必须截断,尽量保持前缀稳定——截取应从尾部开始,而不是头部。
总结:命中率优化路线图
快速检查清单(今天就能做)
- 检查 API 调用日志中的
cached_tokens字段 - 检查 system prompt 是否 > 1024 token(不够就加长)
- 确认动态内容(时间戳、ID)放在 prompt 最后
- OpenAI 用户:添加
prompt_cache_key - Anthropic 用户:在 system prompt 后加
cache_control - 检查 5 分钟 TTL 内相同前缀的平均请求次数是否 > 2
中期优化(一周内)
- SGLang 用户:启用 cache-aware scheduling (
--schedule-policy lpm) - vLLM 用户:切换到 V1 引擎(默认启用 prefix caching)
- 分析 miss 最多的 request pattern,优化 prompt 结构
- 基于业务负载选择驱逐策略(LRU / LFU / priority-based)
- 监控命中率,按天/小时粒度设定告警
终极目标
| 场景 | 目标命中率 | 预期节省 |
|---|---|---|
| 客服 Agent | > 85% | 60-80% 输入成本 |
| 代码助手 | > 80% | 50-70% 输入成本 |
| RAG 系统 | > 75% | 40-60% 输入成本 |
| 多轮对话 | > 90% | 70-85% 预填充延迟 |
缓存命中不是「锦上添花」。在 2026 年,它是一个竞品差距——你的竞争对手可能已经在用相同的模型、相同的数据,但因为命中率高 30%,成本低 50%、响应快 3 倍。
而你,可能还在为同一个 system prompt 付全价。
📅 2026-05-26 | 🏷️ #LLM #CacheHit #CostOptimization #AIEngineering #SystemDesign