Skip to content

Persistence and Recovery.zh

sikkatu edited this page Nov 2, 2026 · 5 revisions

English | Русский | 中文

持久化与恢复

项目验收标准:重启后,同一会话必须复用从 NVMe 恢复的 KV 块 —— 明显更快, 且以磁盘证据证明,而非仅凭速度。

证据清单

同一提示词每次重启后,必须满足以下全部条件:

  1. 响应中 usage.prompt_tokens_details.cached_tokens > 0 (引擎复用了已计算的 prefill 结果)。
  2. 重启后 KVP_CACHE_ROOT/lmcache-server.log 出现 L2/磁盘读取事件 —— 匹配检索模式(retriev|loaded|restore 且含 L2|disk|secondary|file) 的行,而非任意缓存命中行(缓存确实从其存储提供数据),并有物理 NVMe 读取计数器佐证。
  3. L2 字节数没有因重建同样数据而增长 (前后各执行一次 bash scripts/budget-report.sh status)。
  4. TTFT/prefill 相比可比的冷启动基线下降。
  5. 回答文本依然正确(抽查)。

仅凭速度提升不满足验收里程碑。

严格协议(v2)—— test-recovery.sh 如何强制执行

审阅后的协议,已机械化实现在 scripts/test-recovery.sh 中 (PASS/FAIL 是机器判定 —— 仅当所有检查通过时退出码为 0):

  1. 日志位置标记 —— 每个请求发送前在 lmcache-server.log 中记录字节偏移; 只有该标记之后追加的事件才算作本场景的证据。早先运行的内容无法混入。
  2. 重启前先写入 —— 预热请求必须能证明把块写入了 L2 存储 (目录字节数增长 + 写入日志事件)。没有预先存储的数据,后续的「恢复」 什么也证明不了 —— 测试失败。
  3. 区分 L2 与 L1 —— 每次重启后,测试要求日志中出现来自磁盘层的读取事件 (而非可能命中 RAM 的泛化 "Retrieved" 行)。仅有 cached_tokens > 0 明确不被接受。
  4. 硬性就绪失败 —— 重启后在等待预算内 API 未恢复,测试立即失败; 绝不在死掉的服务上继续。
  5. 排除替代解释 —— 重启后有复用却无任何 L2 读事件,被判定为仅 RAM/prefix cache 并记为失败。
  6. 机器判定 —— PASS ⇒ 退出码 0;任一检查失败 ⇒ FAIL,退出码 1, 并列出 failures.txt 说明每条原因。

场景 A —— 重启 vLLM,缓存服务保持运行

bash scripts/test-recovery.sh

脚本用长提示词预热缓存,重启 vLLM 容器,然后重新发送完全相同的请求。 各阶段摘要写入 benchmarks/results/<UTC-ts>-recovery/。

手动等价操作:

# 预热
bash scripts/benchmark.sh cold 3000
# 仅重启 vLLM,等待 API 恢复应答
docker restart mimo-pro-tp4-kvp
until curl -fsS --max-time 3 -H "Authorization: Bearer $(head -n1 live/api_key | tr -d '[:space:]')" http://127.0.0.1:30007/v1/models >/dev/null 2>&1; do sleep 10; done
bash scripts/benchmark.sh after-vllm-restart 3000     # cached_tokens 必须 > 0

场景 B —— 两个服务都重启,NVMe 数据保留

test-recovery.sh 接着执行 stop-cache.sh → start-cache.sh → docker restart → 同一请求。此时缓存服务和 vLLM 都从零启动: 恢复证明了 nixl_store_dynamic 文档化的磁盘索引惰性重建。恢复/查找 耗时从缓存日志中记录。

冷 / 热 / 已恢复 —— 如何区分

观察 含义
cached_tokens = 0 冷(无复用)
cached_tokens > 0,无 L2/磁盘读取事件 热 —— 由 L1/内存提供(缓存服务存活)。这是场景 A 的预期结果:请求复用仍在 L1 中的 KV,因此无需从 NVMe 读取。这是内存命中,不是持久化失败。
cached_tokens > 0 且在完整重启(两个服务、L1 为空)之后有 L2 读取事件 从 NVMe 恢复(这才能证明持久化)

场景 A 与 B 的预期差异(第 18 轮): 仅重启 vLLM 后,缓存服务及其 L1 仍然 存活,因此健康系统会记录 Prefetch request completed (L1+L2): N/N retained keys (N L1, 0 L2) —— 纯 L1 命中。验收脚本不应因此判失败;只有场景 B(完整重启)才要求 L2 prefetch load completed / (N L1, N L2) 证据。

什么会使缓存失效(按设计)

改变任何身份字段 —— 模型版本、分词器、KV 类型、块布局、TP 大小、聊天模板 —— 会让部署进入新命名空间:旧数据不再被寻址。这是隔离,不是删除。 恢复原配置即可继续复用旧数据。

重复测试

scripts/test-recovery.sh 每次运行都新建结果目录;不覆盖任何内容。 引用数值取每种配置 ≥3 次重复的中位数(见基准测试页)。

Clone this wiki locally