别再 Round Robin 了:Prefix Cache-Aware Routing 如何降低 LLM 推理延迟?

📅 2026/8/5 7:40:41
别再 Round Robin 了:Prefix Cache-Aware Routing 如何降低 LLM 推理延迟?
别再 Round Robin 了Prefix Cache-Aware Routing 如何降低 LLM 推理延迟传统 Web 服务做负载均衡时Round Robin 是非常合理的默认选择请求依次分发到不同实例流量大致均匀。但 LLM 推理实例并不是完全无状态的。同一个系统 Prompt、长文档或者多轮会话已经在某个实例计算过时该实例的 KV Cache 可能保留了这段前缀的中间状态。后续请求如果仍然落到这个实例就可以跳过大量重复计算。如果负载均衡器把请求随机分配到另一台机器缓存优势就消失了。这也是Prefix Cache-Aware Routing开始成为推理基础设施热点的原因。Google 公布的 GKE Inference Gateway 实践表明上下文感知路由可以显著提高 Prefix Cache 命中率其生产案例中Vertex AI 的缓存命中率从 35% 提升到 70%。Google CloudGKE Inference Gateway一、Prefix Cache 缓存了什么模型生成每个 Token 时会基于此前 Token 计算 Attention。为了避免每一步都重新计算全部历史推理引擎会保存 Key/Value 状态也就是 KV Cache。假设请求结构是[固定系统提示词 4000 tokens] [固定产品文档 12000 tokens] [用户问题 50 tokens]不同用户的问题会变化但前面的 16000 个 Token 可能完全相同。Prefix Cache 将这段公共前缀对应的 KV 状态保存下来。下一次请求命中缓存时只需要处理新的用户问题。适合复用的前缀包括系统 Prompt代码仓库基础上下文企业知识文档Few-shot 示例多轮会话历史Agent 固定工具描述。二、为什么普通负载均衡会破坏缓存假设有三个推理实例Pod A缓存了文档 X Pod B缓存了文档 Y Pod C没有相关缓存一个携带文档 X 前缀的新请求到来Round Robin 可能分配给 Pod CLeast Connections 可能分配给 Pod BCache-Aware Router 会优先选择 Pod A。因此路由目标不再只是“找到最空闲实例”而是综合考虑缓存匹配度 当前队列长度 KV Cache 剩余容量 GPU 负载 租户优先级 路由分数如果 Pod A 已严重拥塞等待缓存命中可能比去 Pod C 重新计算更慢所以缓存亲和性不能成为唯一指标。三、一个简化的 Go 路由策略首先为请求计算稳定的前缀指纹funcPrefixHash(tokens[]int,prefixLengthint)string{ifprefixLengthlen(tokens){prefixLengthlen(tokens)}h:sha256.New()for_,token:rangetokens[:prefixLength]{_binary.Write(h,binary.LittleEndian,int32(token))}returnhex.EncodeToString(h.Sum(nil))}不能直接对原始字符串取 Hash因为空格、模板渲染和 Tokenizer 版本变化都可能导致实际 Token 序列不同。然后综合缓存和负载评分typeModelPodstruct{IDstringQueueDepthintKVUtilizationfloat64CachedPrefixesmap[string]bool}funcscorePod(pod ModelPod,prefixstring)float64{score:100.0ifpod.CachedPrefixes[prefix]{score80}score-float64(pod.QueueDepth)*12score-pod.KVUtilization*40returnscore}funcSelectPod(pods[]ModelPod,prefixstring)(ModelPod,error){iflen(pods)0{returnModelPod{},ErrNoHealthyPod}best:pods[0]for_,pod:rangepods[1:]{ifscorePod(pod,prefix)scorePod(best,prefix){bestpod}}returnbest,nil}生产环境还会考虑模型版本、并行配置、缓存块位置和预估输入长度。示例重点是说明缓存命中和实时负载必须同时进入路由决策。四、提高命中率要从 Prompt 结构开始即使有智能路由如果每次请求的前缀都不同也无法命中缓存。把稳定内容放前面稳定系统指令 - 稳定工具描述 - 稳定参考资料 - 动态用户信息 - 当前问题不要在开头加入随机值下面这些字段会让所有请求前缀不同request_id 当前精确时间 随机追踪信息 动态排序的 JSON它们应放到后面或者通过独立元数据传递。保证序列化稳定工具列表和 JSON Map 的顺序如果每次变化即使语义相同Token 前缀也可能不同。对公共上下文进行版本化prefix_key tenant document_set document_version model tokenizer文档更新后使用新版本避免错误复用旧缓存。五、哪些指标值得监控只看平均响应时间无法判断 Prefix Cache 是否生效。建议监控指标作用Prefix Cache Hit Rate缓存命中比例Cached Tokens每次请求复用的 Token 数量Time to First Token用户感知的首字延迟Prefill Latency输入前缀处理耗时Queue Time路由到实例后的等待时间KV Cache Utilization缓存空间压力Eviction RateKV 块淘汰频率还要区分“命中次数”和“命中价值”。复用 100 个 Token 与复用 2 万个 Token 的收益完全不同因此可以统计saved_prefill_tokens saved_gpu_seconds cost_saved_per_requestGoogle 的另一份推理优化总结也指出仅通过 Prefix-Aware Routing在不更换硬件和模型的情况下就能降低首 Token 延迟并提高缓存效率。Google CloudEfficient frontier of LLM inference六、Prefix Cache 不是免费的它也会带来新的权衡KV Cache 占用大量显存热点前缀可能让流量集中到少数实例缓存目录本身需要同步多租户环境要防止侧信道和数据泄漏模型或 Tokenizer 更新会让旧缓存失效为命中缓存而等待过久可能适得其反。一个实用策略是设置最大亲和等待时间如果命中实例的预估等待超过阈值就选择空闲实例重新 Prefill。cache_saved_time extra_queue_time - 选择缓存实例 否则 - 选择空闲实例路由目标应该是最低总完成时间而不是最高命中率。结语LLM 推理不是普通无状态 HTTP 服务。请求携带的上下文越长前缀计算成本就越高实例上的 KV Cache 也越有价值。Round Robin 只看请求数量Prefix Cache-Aware Routing 开始理解请求内容和实例状态。要真正获得收益需要同时做好三件事让 Prompt 拥有稳定、可复用的前缀让路由器知道缓存位于哪个实例在缓存收益和实时负载之间动态权衡。模型越来越强之后推理系统的竞争会逐渐落到这些看似底层、却直接决定延迟和成本的工程细节上。