冷缓存、热缓存:为什么你的 LLM 延迟数据在测试环境中具有欺骗性
你的暂存环境显示 p50 延迟为 400ms。你的生产环境仪表盘却显示 1.8 秒。你检查了代码 —— 同样的模型,同样的提示词(Prompt),同样的供应商。部署和发布之间没有任何改动。数据不应该有这么大的分歧,但事实就是如此。
罪魁祸首几乎总是缓存状态。提示词缓存(Prompt caching)—— 大多数团队依赖的最重要的延迟优化手段 —— 在暂存流量模式下的表现与生产流量模式下有着本质的不同。如果你不考虑这种差异,那么你在发布前收集的每一个延迟数据都是虚假的。
你不知道自己正在依赖的缓存
现代 LLM 供应商会进行激进的缓存。Anthropic 对提示词前缀进行缓存,其生存时间(TTL)为 5 分钟,并在每次命中时刷新。OpenAI 会对任何超过 1,024 个 token 的提示词自动进行缓存,其内存留存时间为 5–10 分钟的不活动期,扩展缓存则最长可达 24 小时。Google 则要求至少达到 4,096 个 token 才会激活缓存。
延迟方面的影响是巨大的。对于短提示词(约 1,024 个 token),缓存请求的运行速度快 7%;对于长提示词(150K+ 个 token),速度提升可达 67%。在极端情况下,一个 100K token 的提示词在未缓存时需要 11.5 秒,而在热缓存状态下仅需 2.4 秒 —— 减少了 80%。
问题在于:这些数据描述的是一个完美的“热缓存”状态。在暂存环境中,你运行测试套件,每个请求都会为下一个请求“预热”缓存,前几次之后的每一次测量反映的都是最佳性能。在生产环境中,缓存状态是一个分布 —— 有些请求命中热条目,有些命中冷条目,其比例取决于流量模式,而你无法通过一个仅发送 50 个请求就宣告完成的测试工具来模拟这种模式。
为什么暂存环境会美化数据
暂存环境通过三种方式人为创造了有利的缓存条件。
低流量多样性。 你的测试套件重复发送相同的一小组提示词。每个提示词在第一次调用时预热缓存,随后的每次调用都会受益。在生产环境中,你有成百上千个不同的提示词前缀 —— 其中许多出现的频率太低,以至于在 TTL 过期前无法维持热缓存条目。
可预测的请求时机。 暂存测试是顺序执行或以受控的小规模突发方式执行的。5 分钟的缓存 TTL 永远不会过期,因为你的测试套件在那个窗口期内就完 成了。生产环境的流量则是波动且不均匀的。一个在工作时间很热门的提示词前缀在夜间会变冷,而早上的第一个请求将承受完整的未缓存延迟。
单节点路由。 OpenAI 的缓存是针对单机运行的,并在每个前缀每分钟约 15 个请求时开始溢出到其他机器。在暂存环境中,你较低的请求量使所有内容都保留在带有热缓存的一台机器上。在生产环境中,负载均衡将请求分发到多台机器,每台机器都从空缓存开始。那些溢出的请求就是缓存未命中,它们不会出现在你的暂存指标中。
伤及痛处的百分位数
平均值掩盖了损害。你的 p50 看起来可能很合理,因为大多数请求都命中了热缓存。但 p95 和 p99 —— 这些导致用户投诉和 SLO 违规的百分位数 —— 主要是由冷缓存请求主导的。
考虑一个系统,其中 70% 的请求命中热缓存(400ms),30% 命中冷缓存(1.8s)。平均值看起来是 820ms,这可能通过了你的延迟预算。但 p95 是 1.8 秒,如果冷缓存请求还与更长的提示词或更高的供应商负载相关联,p99 可能会更糟。尾部延迟不是噪声 —— 它是一个完全不同的性能状态,暂存环境从未对其进行过演习。
这种效应在 Agent 系统中会成倍放大。一个单 Agent 循环可能会进行 5–15 次 LLM 调用。如果每次调用有 30% 的概率命中冷缓存,那么在 10 步链路中至少有一次调用命中冷缓存的概率超过 97%。Agent 任务的端到端延迟受链路中最差的一次调用支配,而不是平均值。
