提示缓存命中率上不去?八个常见原因逐个排查
提示缓存最坑的地方是:没生效不会报错。账单还是那么多,日志一切正常,只有你以为省了钱。八成的情况是前缀被某个每次都变的东西污染了。
这篇给一份排查清单。缓存的计费结构见提示缓存是怎么计费的,这里只讲怎么把命中率做上去。
先确认你能看见命中率
排查的前提是有数据。多数厂商会在响应的 usage 字段里返回缓存命中的 token 数,把它记进日志,算出「命中 token / 总输入 token」。
没有这个数就别猜了,先补埋点。凭感觉调缓存是最浪费时间的做法——你改了三处,命中率从 0 变成 0,也不知道是哪处没改对。
八个常见的命中率杀手
一、时间戳。 「当前时间:2026-08-06 14:23:07」写在 system prompt 里,每秒都变,缓存永远命中不了。真需要时间就降低精度到天,或者挪到前缀之后。
二、请求 ID / 追踪 ID。 为了排查方便塞进 prompt 的唯一标识,是最隐蔽的杀手之一,因为它看起来无害。挪到请求头或元数据里,别放进 prompt。
三、用户信息。 用户名、ID、偏好设置放在前缀里,等于每个用户一份缓存。如果你的用户量大而单用户调用少,缓存基本白开。把用户相关内容放到前缀之后。
四、集合遍历顺序不稳定。 工具定义、知识片段从字典或集合里遍历生成,不同进程可能顺序不同。显式排序即可解决,一行代码的事。
五、检索片段放在了前面。 检索结果每次都变,如果它排在 system prompt 前面,后面全废。顺序应该是:固定指令 → 固定工具 → 检索片段 → 历史 → 用户输入。
六、system prompt 频繁改版。 实验期每天改 prompt,缓存刚建好就失效。可以在实验期先不指望缓存,等 prompt 定型再算这笔账。
七、多实例之间缓存不共享。 有些实现里缓存是按连接或按实例维度的,你有十个进程轮询,可能就是十份独立缓存,各自都要写入。这一点要看厂商的具体说明。
八、超出存活时间。 低频调用场景下,缓存等不到复用就过期了。这不是 bug,是场景不适合——低频场景本来就不该指望缓存。
请求结构应该长什么样
把请求想象成分层,从最稳定到最易变:
- 系统指令层:角色设定、输出格式约束、禁止事项。几乎不变。
- 能力定义层:工具/函数 schema、few-shot 示例。版本内不变。
- 常驻知识层:产品手册摘要、术语表这类每次都要带的固定知识。
- 动态检索层:本次相关的文档片段。每次不同。
- 会话历史层:多轮对话。每轮追加。
- 本次输入层:用户这一句。
前三层是缓存的目标,后三层不指望。按这个顺序拼装请求,命中率自然就上去了。
一个容易忽略的收益:延迟
缓存不只省钱,还省时间。命中的部分不用重算,首 token 返回会明显更快。交互式产品里,这个收益有时比省下的钱更值钱。
所以评估缓存效果时,建议同时看两个指标:命中率带来的成本下降,和首 token 延迟的变化。后者更容易向产品同事解释。
一次典型的排查过程
举一个很常见的排查路径,供参考。
某个客服问答服务开了缓存,一周后发现账单几乎没变。第一步先看命中率——发现是零。这就把问题限定在「前缀不稳定」上,不用再怀疑厂商或计费。
第二步,把连续两次请求的完整请求体打印出来做逐字符 diff。这一步是整个排查的关键动作,很多人跳过它去猜,反而绕远路。diff 出来通常一眼就能看到差异在哪。
第三步,如果 diff 显示差异出现在很靠前的位置,那从那个位置往后的所有内容都在白发。常见的元凶就是前面列的那八条:时间戳、请求 ID、用户信息、遍历顺序。
第四步,改完再看命中率。注意缓存需要一点时间积累,改完立刻看可能还是低,观察一两个小时更准。
整个过程的核心是用 diff 代替猜测。缓存命中是逐字符匹配的,任何猜测都不如直接看两次请求到底差在哪。
改造时的三个注意事项
一、改前缀等于让现有缓存全部失效。 上线新版 system prompt 的那一刻,所有缓存重建,短时间内成本会有一个小尖峰。这属于正常现象,别误判为出了问题。
二、灰度期间命中率会偏低。 新旧两版前缀并存时,缓存被分成两份,各自的复用次数都下降。所以灰度期的命中率数据不能直接和全量后对比。
三、多实例部署要确认缓存维度。 缓存是账户级、密钥级还是连接级,各家实现不同。如果是连接级,你的十个进程就是十份独立缓存,命中率天然被稀释。这一点以厂商文档为准,必要时提工单问清楚。
命中率做到多少算合格
没有统一标准,取决于你的请求结构。一个参考思路是:先算理论上限——把请求拆成固定部分和变化部分,固定部分占总输入的比例就是理论最高命中率。
如果理论上限是六成,实际做到五成多,那已经很好了;如果理论上限六成而实际只有一成,那就是有污染,回到上面八条逐个查。
理论上限本身太低(比如只有两成),说明你的请求结构里固定部分占比小,缓存不是主要杠杆,应该先去做别的优化——见大模型 API 降本十招。
三个高频问题
问:命中率一直在波动正常吗? 一定幅度的波动正常,因为它受请求密度影响——请求稀疏时缓存更容易过期。但如果波动到接近零,那多半是前缀偶尔被污染,去查那些「偶尔才出现」的字段。
问:改了 system prompt 之后命中率归零了? 正常。前缀变了,旧缓存全部失效,需要重新积累。观察一段时间会回升。
问:能不能只缓存一部分内容? 缓存是按前缀连续匹配的,没法跳着缓存。想让某段内容进缓存,就得把它挪到前面并保持稳定。
一句话记住
缓存命中是逐字符前缀匹配,不是模糊匹配。任何一个字符的差异,都会让它后面的所有内容失去命中资格。所以优化命中率的全部工作,说到底就是一件事:把请求的前半截钉死,让它每次都一模一样。做到这一点,命中率自然就上去了;做不到,其他调优都是白费力气。
接着往下看
把命中率做上去之后,下一步是把这份收益量化进预算:用月成本估算器分别按有缓存和无缓存算两遍,差额就是这项优化的月度价值。想了解缓存的完整计费结构(命中价、写入价、存活时间三者怎么共同决定成本),读提示缓存是怎么计费的;想知道缓存和批处理该怎么搭配使用,读提示缓存和批处理该用哪个。