KVConnector Event Logic
BlockStored
含义
记录了 block 注册到 prefix cache 或保存到远端后的元数据,核心字段:
| 字段 | 说明 |
|---|---|
block_hashes |
block 的 hash 列表 |
parent_block_hash |
前一个 block 的 hash(prefix 链) |
token_ids |
block 包含的 token IDs |
block_size |
block 大小(token 数) |
medium |
存储介质("GPU" / "DISK" / "remote" 等) |
extra_keys |
影响 hash 计算的额外 key(MM 特征、cache_salt 等) |
group_idx |
KV cache group 索引 |
两种 BlockStored 对比
| 维度 | block_pool | connector |
|---|---|---|
| 产生时机 | 调度阶段(forward 之前) | forward 完成后(远端保存结束) |
| 触发条件 | block 插入 cached_block_hash_to_block 字典 |
外部存储完成,通过 get_kv_events() 查询 |
| KV 状态 | KV 数据还未计算,只是预告 | KV 数据已保存到远端 |
| 目的 | 注册到 prefix cache,后续请求可命中 | 通知调度器远端已就绪,可从远端加载 |
| 产生位置 | block_pool.cache_full_blocks() |
各 connector 实现(如 lmcache_engine.get_kv_events()) |
| medium | 固定 "GPU" |
因 connector 而异("GPU", "DISK", "remote") |
事件流
block_pool.cache_full_blocks() ─┐
├─→ Scheduler 合并 ─→ kv_event_publisher.publish()
kv_connector.get_kv_events() ──┘
BlockRemoved
含义
记录了 block 从 prefix cache 或远端被清除后的元数据。
block_pool 的触发逻辑:
请求 A 结束
→ free_blocks()
→ block 加入 free_block_queue
→ hash 保留,索引保留,GPU 数据保留
│
请求 C 进入,分配到同一个 block
→ get_new_blocks()
→ _maybe_evict_cached_block(block)
→ cached_block_hash_to_block.pop(hash) ← 清除索引
→ block.reset_hash() ← 清除 hash 字段
→ BlockRemoved 事件 ← 此时才触发
核心原因:保留 hash 是为了让后续相同 prefix 的请求可以 prefix hit,直接从远端加载 KV 而不必重算。只有当 block 被真正复用时才清除旧记录。
Connector 的 BlockRemoved:
| Connector | 是否产生 | 说明 |
|---|---|---|
| block_pool | ✅ | 驱逐时产生 |
| Offloading Connector | ✅ | 远端/CPU 上 block 被删除时产生 |
| LMCache Connector | ❌ | 目前只产生 BlockStored,不报告远端删除 |
字段
| 字段 | 说明 |
|---|---|
block_hashes |
被清除的 block hash 列表 |
medium |
存储介质 |
group_idx |
KV cache group 索引 |
Event 聚合
Worker 聚合
多 Worker 场景下(如 tensor parallel),同一个 block 可能被多个 Worker 同时保存。聚合逻辑:
Worker 0 ─→ BlockStored(H0, ...) ─┐
│
Worker 1 ─→ BlockStored(H0, ...) ─┼─→ Counter[event] 统计出现次数
│
Worker 2 ─→ BlockStored(H0, ...) ─┘
↓
只在 count == num_workers 时才保留
聚合 Key(__hash__)
| 事件类型 | 聚合 key 组成 |
|---|---|
BlockStored |
10 个字段:block_hashes, parent_block_hash, token_ids, block_size, lora_id, medium, extra_keys, group_idx, kv_cache_spec_kind, kv_cache_spec_sliding_window |
BlockRemoved |
3 个字段:block_hashes, medium, group_idx |
两个事件必须所有这些字段完全相同,才会被算作”同一个事件”进行聚合。
补充:驱逐 ≠ 清 GPU
| 操作 | 清除什么 | 时机 |
|---|---|---|
reset_hash() |
只清 Python 对象的 _block_hash 字段 |
驱逐时(get_new_blocks) |
_zero_block_ids() |
清 GPU 内存中的 KV 数据 | forward 之前(model runner) |
| forward | 新 KV 数据写入 | forward 阶段 |