1.4 命中、未命中与失效


文档摘要

1.4 命中、未命中与失效 本节摘要:版图画好之后,最后一件事是把"命中"的标准划清。传统缓存的键、值、失效三要素进入 LLM 场景发生三处变形:键从 URL 变成有序前缀或嵌入向量,值从响应体变成 KV 张量或生成结果,失效从"源数据变了"变成"前缀变了、模型版本变了"。本节以一次"改个日期、命中率归零"的复盘收束全章,把前缀敏感性变成可操作的布局法则,并把接力棒交给第 2 章。 改动一个字,命中率为什么归零 传统缓存的世界里,三要素的规则简单明确:HTTP 缓存的键是 URL 加少量请求头,值是响应体,键精确相等即命中,TTL 到期或源站数据变更即失效。判断一个键是否命中,是集合意义上的"相等",与字符顺序无关——查询参数换个顺序可能算成不同的键,但那也只是"字符串不同",与位置无关。

1.4 命中、未命中与失效

本节摘要:版图画好之后,最后一件事是把"命中"的标准划清。传统缓存的键、值、失效三要素进入 LLM 场景发生三处变形:键从 URL 变成有序前缀或嵌入向量,值从响应体变成 KV 张量或生成结果,失效从"源数据变了"变成"前缀变了、模型版本变了"。本节以一次"改个日期、命中率归零"的复盘收束全章,把前缀敏感性变成可操作的布局法则,并把接力棒交给第 2 章。

改动一个字,命中率为什么归零

传统缓存的世界里,三要素的规则简单明确:HTTP 缓存的键是 URL 加少量请求头,值是响应体,键精确相等即命中,TTL 到期或源站数据变更即失效。判断一个键是否命中,是集合意义上的"相等",与字符顺序无关——查询参数换个顺序可能算成不同的键,但那也只是"字符串不同",与位置无关。

LLM 缓存的键是有序的。前缀类缓存——显存、框架、平台三层——的键不是整段文本的哈希,而是"从第一个 token 开始的最长公共前缀"。这一个差别,推翻了传统缓存的三条直觉,也回答了标题的问题:改在开头的那个字,让所有请求的前缀从第 1 个 token 就彼此不同,键自然全盘失配。下面把三处变形逐一摊开。

变形一:键从离散字符串变成有序前缀或向量。 传统键只有相等与不等两种关系;前缀键支持"部分命中"——已缓存的前缀是 A、B、C、D 四个 token,新请求是 A、B、C、E,前三个 token 命中,只需为最后一个 token 补算 KV;而 A、C、B、D 看似只交换了两个位置,命中为零。应用层则把键换成嵌入向量,用相似度阈值判定,允许"没有一字相同但意思相同"的模糊命中。键的性质决定了这一层能做精确复用还是模糊复用。

变形二:值从可读的响应体变成巨型张量。 HTTP 缓存的一条响应从几 KB 到几 MB,可读、可压缩、可跨服务复制;一份长上下文的 KV 张量可达 GB 级(第 2 章会给出精确算法),不可读、绑定具体模型与权重精度——换模型、换量化格式,值全部作废。值的大小直接决定"缓存能存多少条",于是淘汰策略(谁被挤出显存)从实现细节升级成架构问题,这也是第 2 章 PagedAttention 登场的舞台。

变形三:失效从"数据变了"变成"上下文前缀变了"。 传统缓存的失效几乎总与源数据有关;LLM 缓存里,哪怕业务数据一字未动,只要提示词的任何一个位置变化——一个日期、一个用户 ID、一次检索结果——该位置之后的全部 KV 都失效。另有一条 LLM 特有的失效线:模型版本升级。权重变了,旧 KV 的数值就是错的,缓存哪怕键完全相同也必须作废;权重精度与量化格式的变更同理。

传统缓存与 LLM 缓存的语义对照表

维度 传统 HTTP 缓存 LLM 前缀类缓存(显存/框架/平台层) LLM 语义缓存(应用层)
缓存键 URL 与请求头,离散字符串 从首个 token 起的有序前缀 查询的嵌入向量
键匹配 精确相等 最长公共前缀,支持部分命中 相似度超过阈值即命中
缓存值 响应体,KB 级,可读 KV 张量,可达 GB 级,绑定模型与精度 完整生成结果,可读
命中收益 省一次回源请求 省掉重复 Prefill 的算力与费用 免掉整次推理
失效条件 TTL 到期、源数据变更 前缀任一位置变化、模型版本或精度变更 模型更新、答案时效、相似度误判
淘汰 容量驱动的 LRU 为主 显存分页、引用计数与 LRU 混合 容量与时效双控

前缀敏感性:位置就是成本

前缀键的因果来源在 KV 本身。位置 i 的 KV 只由前 i 个 token 决定——第 2 章会从注意力公式推出这一点——所以改动第 k 个位置的 token,k 之后的全部 KV 作废,k 之前的仍然有效。部分命中由此而来:改动越靠后,保留的复用越多;改动越靠前,作废的越彻底。"改开头最贵、改结尾最便宜"不是经验之谈,是注意力因果结构的直接推论。

小例子印证一遍。已缓存前缀 A、B、C、D,新请求 A、B、C、E 命中四分之三,只为 E 补算一个 token 的 KV;新请求 D、B、C、A 只动了首尾两个位置,命中为零——在有序键的世界里,顺序即身份。应用层语义缓存是个例外,它干脆不看来时路,只看问题像不像,代价是把"命中的确定性"换成了"答错的可能性"。

失效的粒度也随层而变。显存层与框架层通常没有 TTL 这个概念——它们的失效只有两种:请求结束(显存层)或容量压力下的淘汰(框架层);平台层把 TTL 重新引入,常见的是几分钟到几小时的窗口,窗口内重复请求命中,超窗重新 Prefill 并计一次写入费;应用层的时效则是业务属性,答案本身会过期,需要单独的时效字段。同一个"TTL"名词,在四层里管的是四件不同的事,排障时先确认自己站在哪一层,再去找对应的失效开关。

缓存命中会影响生成质量吗

前缀类缓存不会,这是它最值得信赖的性质。KV 张量是确定性计算的产物:同样的模型权重、同样的前缀,无论这些 KV 是本次算出来的还是从缓存里取来的,数值完全一致,后续生成的分布也完全一致。命中前缀缓存等价于"省去了重算",等价于数学意义上的零损耗——它改变的是成本曲线,不改变输出分布。语义缓存则不同:它返回的是另一次推理的结果,采样随机性、模型更新、阈值边界上的近似匹配,都可能让返回的答案偏离当前请求的期望。所以工程实践里,前缀类缓存可以放心全量开启,语义缓存必须带着阈值、时效和兜底通道上线——1.3 节那条"越往上收益越大、风险也越大"的规律,到这里有了精确的技术解释。

案例复盘:一个日期打掉的命中率

背景:某团队接入平台 context caching。系统提示词约 4000 token(业务规则、话术约束),另有每次请求约 1000 token 的动态内容;日调用 1 万次,平台承诺命中后输入按十分之一计价。团队预期输入成本至少降六成。
操作:提示词模板的第一行是"今天是 2026 年 9 月 7 日,以下回答须符合当日生效的规则",由定时任务每天凌晨更新。上线一周后拉取统计:缓存命中率 0.3%,输入成本纹丝不动。
结果:排障确认平台缓存服务一切正常,问题出在键上——日期位于提示词最前面,每天零点之后,所有请求的前缀从第一个 token 就与昨天不同,缓存全部作废;一天之内命中率倒是正常的,只是每天都从零开始。把日期挪到提示词末尾、静态规则全部前置后,命中率升到 94%。
解读:两种布局的成本对比(按输入全价 2 元每百万 token、命中价 0.2 元每百万 token 计算,每请求输入 5000 token):

布局 命中率 单请求输入成本 日成本(1 万次)
日期置于开头 约 0% 0.010 元 100 元
日期置于末尾 94% 0.0032 元 32 元

一字之差,日成本差三倍。这个复盘的价值在于把抽象的"失效"翻译成了可执行的动作:失效检查的第一问,永远是"变动的字段在提示词的什么位置"。
变式:同一条法则派生出一组布局清单。随机字段(请求 ID、用户昵称、时间戳)禁止出现在提示词前部;A/B 实验的两套提示词会分裂前缀,各自独立累积命中,实验评估时要分别统计命中率;RAG 场景里检索片段天然易变,只能放在动态区;会话历史按轮次追加在尾部,恰好满足"只在末尾生长"的理想形态。凡是"只在末尾生长"的输入结构,都是前缀缓存友好的。

收束:从账单到缓存的三步推理

本章走完了一条从现象到机制再到框架的路。1.1 用账单证明重复付费是结构性的:8 轮会话付费 20 万 token,新信息只占百分之一。1.2 把重复计算定位到 Prefill,并给出两段式成本模型:Prefill 吃算力、Decode 吃带宽,浪费集中在前者。1.3 给出四层回收版图,每层的三元组确定了"键是什么、能免掉什么"。本节补上判定规则:键是有序前缀,命中可以是部分的,失效发生在前缀或模型版本变化的地方——位置就是成本。

四节合起来,回答了章名的问题。缓存存在于 LLM 系统,根子在一笔经济账:算力是预付的,缓存是回收——Prefill 为每个 token 预付了算力,只要前缀不变,这笔预付就该被反复回收,而不是每次请求重新预付。第 2 章进入版图最底层,拆解 KV Cache 本体:它为什么恰好长成"值"的那个形状、一份上下文要占多少显存、又会在哪里把显存撑爆。


作者与出处
原作者: 灏天文库
整理: 灏天文库整理
本站整理收录,版权归原作者/开源协议所有;欢迎通过原文链接访问源仓库。
发布者: 作者: 灏天文库 转发
评论区 (0)
U