9. 最佳实践
一句话理解:KV 缓存层的收益来自复用率,复用率来自「前缀长什么样、请求去哪台、数据沉到哪层」三个决策的质量——最佳实践就是围绕这三个决策建立可度量、可调参、可降级的工程纪律。
9.1 前缀设计:让 KV 可复用
- 稳定的前缀骨架:system prompt、工具定义、few-shot 示例放在请求最前部且字节稳定——任何扰动(时间戳、随机 ID)都会让哈希失效,把复用率打到零。建议:易变内容放 prompt 末尾,或使用 extra keys 机制(vLLM 已支持把 extra key 按来源打标参与哈希)。
- 会话 ID 亲和:多轮对话用
session_id路由到同一实例(SGLang--enable-session-radix-cache的会话感知逐出同理),避免历史 KV 被 LRU 挤掉。 - Agent 循环的上下文卫生:规划-执行-反思循环中,把稳定子图(系统指令 + 工具 schema)与易变轨迹(中间结果)分段组织,稳定段尽量复用。
9.2 路由:命中率与负载的权衡
- 加权打分,不纯追命中:
score = α·命中长度 − β·队列深度 − γ·负载,α/β/γ 按 SLO 调;纯命中路由会把同前缀流量打成单实例热点。 - 索引是建议不是契约:路由预测命中、实例实际未命中(索引滞后)的失效率要监控,超过阈值就调索引刷新频率。
- 池间粗路由:Gateway 先按前缀分片粗选实例池,池内细选——减少全局索引的扇出压力。
9.3 量化与压缩:分层量化收益最大
- 热 FP16 / 冷 FP8:活跃 decode 的 block 用 FP16 保质量,下沉到慢层时转 FP8——「时间换空间」的细粒度版本,比全局 FP8 质量损失小。
- 量化要与 kernel 联动:FP8 KV 的收益依赖 FlashMLA/FlashInfer 等 kernel 支持,升级前先验证注意力精度回归(如 LongBench 类基准)。
- 搬运管线插变换:用 LMCache SERDE 这类接口在迁移途中做压缩/token dropping,让「下沉」本身就带压缩红利。
9.4 分层策略:下沉优先,提升谨慎
- demote-first:GPU 逐出时先尝试写 CPU/SSD,写不下才丢——保证慢层有持续水源。
- 提升要过成本闸:慢层命中读回 GPU 前,先算「读 + 写 + 驱逐副作用」是否小于重算 prefill;长前缀(几千 token 以上)几乎总是提升,短前缀直接重算。
- 逐出加优先级:system prompt、高复用公共前缀 pin 住或提高权重;单用户一次性长文最低优先级。SGLang 的软硬 pin、Mooncake Store 的软硬 pin 都是这个语义。
9.5 容量与水位
- 按 token 不按请求规划:容量 = 层容量 / 每 token 字节数;每 token 字节数 = 2×层数×KV heads×head_dim×dtype 字节。
- GPU 水位保持余量:KV 池占用率建议控制在 80% 以下,给突发长请求与迁移抖动留缓冲;持续超过则说明该扩池或加层。
- 逐出/下沉速率是先行指标:速率持续高企说明缓存在「 churn」——存入马上被挤掉,净收益为零,此时应扩容而不是调策略。
9.6 可观测与 SLO
必须内置的告警(详见第 5 章指标表):
| 告警 | 含义 |
|---|---|
| prefix 命中率骤降 | 路由亲和失效 / 逐出过狠 / 前缀内容漂移 |
| 路由预测失效率高 | 全局索引滞后 |
| TTFT P99 涨 + SSD 命中涨 | 提升策略太激进,慢层拖尾 |
| 传输带宽利用率低 | 调度没喂饱链路,浪费 RDMA 投资 |
SLO 建议:TTFT 分位优先于均值(缓存命中方差极大);对「缓存未命中率」单独设预算(如 < 30%),它是 TTFT 长尾的直接来源。
9.7 常见反模式
- 在 prompt 中间塞随机量(请求 ID、当前时间)——前缀哈希全碎,复用率归零;
- 缓存层与请求关键路径同步耦合——Store 抖动直接拖垮 TTFT,迁移必须异步;
- 只监控命中率不监控搬运量——高命中率 + 高 churn = 白搬;
- PD 分离不做流水线——等全量 KV 到齐再 decode,白白浪费 RDMA 带宽投资;
- 量化只做显存不做传输——FP8 KV 的另一半收益在传输与分层,错过等于只拿了一半红包。
小结
- 前缀设计决定复用率上限:稳定骨架 + 易变内容后置 + 会话亲和。
- 路由与分层决定复用率兑现:加权打分防热点,下沉优先保水源,提升过成本闸。
- 容量与观测决定复用率可持续:按 token 规划、盯逐出速率、给 TTFT 设命中率预算。