真实面经题目 · 原创解析

长上下文推理中 KV Cache 为什么可能被污染,如何做缓存隔离、清理和复用边界控制?

这题考的是大模型推理缓存的正确性与安全边界:KV Cache 本身是某个模型、某段 token、某套位置编码和注意力 mask 下的中间状态;一旦跨请求、跨会话、跨租户、跨模板版本或跨可变上下文错误复用,就可能产生答案串扰、隐私泄漏、事实陈旧或位置错乱。

出现于:腾讯 · 算法

60 秒回答模板

我会先区分两类 KV Cache:一类是单次请求 decode 过程中的历史 K/V,生命周期应该严格绑定 request 或 session;另一类是 prefix cache,把相同前缀的 K/V 复用给多个请求以节省 prefill 成本。所谓污染,通常不是 K/V 数值自己变脏,而是缓存被错误复用或没有及时失效:例如把 A 用户的长上下文前缀复用到 B 用户,系统 prompt 模板变了但 key 没变,LoRA adapter 或模型版本不同却共享缓存,滑动窗口丢弃 token 后位置没有对齐,工具结果或检索证据更新但旧前缀仍被命中。解决思路是把缓存边界显式化。缓存 key 至少要包含模型权重版本、tokenizer、token id 序列或其 hash、position scheme、attention mask、系统模板版本、adapter、租户或权限域等会影响 K/V 语义的因素;decode KV 默认 request 私有,prefix cache 只能复用不可变、可共享、权限一致的前缀。对可变上下文要做版本化和失效,对跨租户和隐私内容要禁用共享或按安全域隔离。清理上要有 TTL、LRU、引用计数、请求结束释放、取消释放、内存水位淘汰和异常回收。观测上要记录 cache hit 来源、key mismatch、跨域命中拦截、污染回归测试和 canary prompt。核心原则是:能复用的只能是语义完全相同且安全域一致的前缀,不能为了命中率牺牲正确性和隔离性。

考点 污染本质
难度 真实面经题
回答目标 让候选人能把 KV Cache 污染讲清楚为推理状态复用边界问题,并给出请求生命周期、prefix key 设计、安全域隔离、版本失效、长上下文清理、引用计数、观测和回归测试方案。

深入解析

01

先定义什么叫污染

KV Cache 污染不是指缓存里的浮点数随机坏掉,而是缓存状态与当前请求不匹配。常见表现包括回答带入别的会话内容、引用旧上下文、忽略新工具结果、跨用户泄漏、位置编码错位、adapter 不一致导致输出异常,或 prefix cache 命中后答案稳定偏错。

02

decode KV 应绑定请求生命周期

自回归 decode 阶段的 K/V 是当前请求已经生成或输入过的 token 的注意力记忆,默认应绑定一个请求或一个明确的会话分支。并发 batch 可以共享调度和内存池,但不能共享语义状态。请求结束、取消、超时或分支回滚时,对应 block 要释放或引用计数递减。

03

prefix cache 的 key 必须足够严格

Prefix cache 能复用相同前缀的 prefill 结果,但相同不能只看文本字符串。K/V 依赖 token id、模型权重、tokenizer、位置编码配置、attention mask、系统模板、adapter、视觉或工具特殊 token 等因素。任何一个会改变前缀表示的因素变化,都应导致 cache key 不同或缓存失效。

04

安全域隔离优先于命中率

企业知识、用户隐私、租户数据、付费权限和会话记忆不能随便进入全局共享 prefix cache。可以把 cache 分成 public prefix、tenant prefix、user/session prefix 等安全域;含隐私或检索证据的前缀默认只在同一权限域内复用,必要时完全不共享。

05

可变上下文要版本化失效

系统 prompt、工具结果、RAG 证据、用户画像、会话摘要和模板字段都可能更新。如果缓存 key 只记录模板名称而不记录版本或内容 hash,就会复用旧 K/V。更稳妥的做法是对可变前缀做内容 hash、版本号或构建批次标记,更新后自动失效旧缓存。

06

长上下文裁剪会带来位置边界问题

滑动窗口、attention sink、chunked prefill、分页 KV 和上下文压缩都会改变当前序列能看到的历史范围。清理旧 block 时必须同步更新 position、mask、block table 和可见窗口,不能让模型以为某些历史 token 仍可见,也不能把旧位置的 K/V 接到新位置上继续用。

07

调度层要支持引用计数和回滚

推理服务通常会把 KV 放在分页 block 或内存池里。多个序列复用 prefix 时需要引用计数;生成分支、投机解码、取消请求或失败重试时需要释放未提交 block。否则轻则显存泄漏,重则 block 被错误复用到其他序列,形成难排查的串扰。

08

清理策略要兼顾内存和正确性

清理机制包括请求结束释放、TTL、LRU/LFU、内存水位淘汰、低优先级 prefix 淘汰、异常任务回收和周期性一致性扫描。淘汰时要保证没有活跃引用,不能在序列仍依赖某段 K/V 时回收;保留时也要限制生命周期,避免陈旧上下文长期命中。

09

观测和测试要覆盖隔离失败

需要记录 cache hit/miss、hit 的安全域、key 组成版本、跨域命中拦截、block 引用计数异常、释放延迟和 cache 相关错误。测试上可以设计两组带互斥秘密词的会话、模板版本切换、adapter 切换、租户切换和滑动窗口边界用例,验证不会串答案。

易错点

  • 把 KV Cache 污染解释成显存随机错误,没有指出错误复用和失效边界才是主要风险。
  • prefix cache key 只看 prompt 文本,不包含模型版本、tokenizer、position、mask、adapter 和模板版本。
  • 为了提高命中率把用户输入、租户知识或 RAG 证据放进全局共享缓存。
  • 请求取消、超时或生成分支回滚后不释放对应 KV block,导致显存泄漏或状态串扰。
  • 系统 prompt 或工具结果更新后不失效旧缓存,模型继续基于旧前缀回答。
  • 滑动窗口或上下文压缩后没有同步维护 position 和 attention mask,造成历史 K/V 错位。
  • 只做 LRU 淘汰,不做引用计数和活跃序列保护,可能清理仍在使用的缓存。
  • 缺少跨会话、跨租户、跨模板版本和跨 adapter 的隔离测试,只看 cache hit 率。

面试官追问

KV Cache 的 key 只用 prompt 文本 hash 可以吗?

不够。K/V 还依赖 tokenizer 后的 token id、模型权重、位置编码配置、attention mask、系统模板版本、adapter 和特殊 token 等因素。文本一样但 tokenizer 或模型版本不同,缓存也不能复用。

哪些前缀可以安全做全局 prefix cache?

通常只有完全公开、不可变、与用户权限无关的公共系统前缀或模板片段适合全局共享。只要前缀包含用户输入、租户知识、会话摘要、RAG 证据或隐私字段,就应按安全域隔离,甚至禁用共享。

清理 KV Cache 会不会影响正在生成的请求?

如果实现正确,不会。调度层应通过引用计数或序列状态判断 block 是否仍被活跃序列使用。只有无引用或过期的缓存才能被回收,不能因为内存压力直接清掉仍在用的 K/V。

滑动窗口场景下怎么避免位置错乱?

滑动窗口删除旧 token 后,要同步维护可见 token 范围、position id、attention mask 和 block table。新 token 只能 attend 到窗口内允许的 K/V,不能把旧位置的 K/V 当成新上下文继续拼接。

如何验证没有跨会话污染?

可以构造两个会话,分别注入互斥的秘密词或事实,然后交替并发请求、启用 prefix cache、切换模板和取消请求,检查任何一方答案都不能包含另一方事实。同时检查 cache hit 日志是否跨安全域。

为了提升命中率能否放宽隔离?

不应把正确性和隐私边界让位于命中率。可以优化公共前缀、模板稳定性和调度复用,但含权限或用户内容的缓存必须保持隔离。命中率指标要和污染拦截、泄漏测试、答案一致性一起看。