LMCache Pin/Persistence 实战:通过控制器 API 持久化请求的 KV Cache
2026/9/16 20:46:33 网站建设 项目流程

LMCache Pin/Persistence 实战:通过控制器 API 持久化请求的 KV Cache

【免费下载链接】LMCacheLMCache: Supercharge Your LLM with the Fastest KV Cache Layer项目地址: https://gitcode.com/GitHub_Trending/lm/LMCache

导读

本文讲解 LMCache 的Pin/Persistence(固定/持久化)能力:如何在 LMCacheEngine 外部,通过控制器(Controller)提供的 HTTP API,将一个请求的 KV Cache 按 token 序列“钉住”,使其在存储后端中保留而不被驱逐。你将学会完整的端到端操作流程——从启动 vLLM + LMCache 实例、启动控制器,到发送推理请求、获取 token 序列,再到调用/pin接口完成持久化并解读返回结果。文末还会结合仓库源码,深入剖析 Pin 操作从 HTTP 入口到存储后端的完整调用链,以及它与缓存驱逐机制的底层关系。

本文以仓库中的 pin 示例目录 及配套配置文件(example.yaml)为操作骨架,相关接口实现与文档可进一步参考 LMCache 控制器 API 文档 与 控制器内部 API 服务。

一、Pin 是什么:从“缓存”到“持久化”

LMCache 的核心职责是为 LLM 推理提供高性能的 KV Cache 层:推理过程中的 KV cache 会被分块(chunk)存储到 GPU、本地 CPU 内存或远端存储后端中,并在后续请求命中时复用,从而省去重复预填充(prefill)的计算开销。

但 KV cache 本质上是“缓存”,默认受容量上限与驱逐(eviction)策略约束。当缓存空间不足时,LRU 等策略会回收旧的 chunk,这可能导致你希望长期保留的热点数据被换出。

Pin 接口解决了这一问题:它允许外部调用者(比如一个调度系统、代理或运维脚本)显式指定一段 token 序列,要求 LMCache 将其对应的 KV cache 固定下来,使其不会被驱逐。文档中将其描述为:

在 LMCacheEngine 外部演示如何 pin/persist(固定/持久化)一个请求的 KV cache。

从源码接口看,Pin 的核心语义是:

pin(instance_id: str, location: str, tokens: List[int]) -> (event_id: str, num_tokens: int)
  • instance_id:目标 LMCache 实例标识;
  • location:KV cache 所在的存储位置(后端);
  • tokens:要固定的 token id 序列;
  • 返回event_id(操作事件 ID)与num_tokens(被固定下来的 token 数)。

这与“移动(move)”“压缩(compress)”“清理(clear)”等操作一起,构成了 LMCache 控制器对外提供的 KV cache 管理能力集合,相关接口在 控制器 KV 控制器实现 中均有对应实现。

二、环境准备与端口规划

开始之前,请确认以下前提:

  • 至少 1 张 GPU(示例使用CUDA_VISIBLE_DEVICES=0指定);
  • 端口规划如下:
端口服务说明
8000vLLM 推理服务接收推理请求与 tokenize 请求
8001LMCache workerexample.yaml中通过lmcache_worker_ports配置
9000LMCache 控制器提供/pin等管理 API
9001控制器 monitor(pull 端口)控制器拉取 worker 心跳/信息

示例中的模型为meta-llama/Llama-3.1-8B-Instruct,需确保已能通过 vLLM 正常加载。

三、第一步:编写 LMCache 实例配置example.yaml

在 pin 示例目录 中提供了完整的配置文件,内容如下:

chunk_size: 256 local_cpu: True max_local_cpu_size: 5 # cache controller configurations enable_controller: True lmcache_instance_id: "lmcache_default_instance" controller_pull_url: "localhost:9001" lmcache_worker_ports: 8001 # Peer identifiers p2p_host: "localhost" p2p_init_ports: 8200

各参数含义:

  • chunk_size: 256:KV cache 分块大小(token 数),LMCache 以 chunk 为粒度存储与检索 KV cache;
  • local_cpu: Truemax_local_cpu_size: 5:启用本地 CPU 内存作为 L2 存储,容量上限为 5GB,Pin 操作的目标位置LocalCPUBackend即指这一层;
  • enable_controller: True:开启缓存控制器,使其能够接收外部的/pin等管理指令;
  • lmcache_instance_id: "lmcache_default_instance":实例 ID,后续调用/pininstance_id字段必须与此一致;
  • controller_pull_url: "localhost:9001":worker 上报给控制器的地址,对应控制器的 monitor 端口 9001;
  • lmcache_worker_ports: 8001:LMCache worker 监听端口;
  • p2p_host: "localhost"p2p_init_ports: 8200:节点间 P2P 通信(如跨实例共享)的标识信息。

四、第二步:启动 vLLM 引擎与 LMCache 控制器

4.1 启动 vLLM 引擎(端口 8000)

CUDA_VISIBLE_DEVICES=0 LMCACHE_CONFIG_FILE=example.yaml vllm serve meta-llama/Llama-3.1-8B-Instruct --gpu-memory-utilization 0.8 --port 8000 --kv-transfer-config '{"kv_connector":"LMCacheConnectorV1", "kv_role":"kv_both"}'

要点说明:

  • LMCACHE_CONFIG_FILE=example.yaml指定 LMCache 配置文件,vLLM 集成层会读取它来初始化 LMCache 实例;
  • --kv-transfer-config '{"kv_connector":"LMCacheConnectorV1", "kv_role":"kv_both"}'指定 KV 传输配置:LMCacheConnectorV1是 LMCache 为 vLLM 提供的 KV 连接器,kv_both表示该实例同时承担 KV cache 的保存(store)与加载(load)角色,使推理过程中的 KV cache 能够被 LMCache 捕获并存入配置的存储层。

4.2 启动 LMCache 控制器(端口 9000,monitor 端口 9001)

lmcache_controller --host localhost --port 9000 --monitor-port 9001

从 控制器入口源码 可以看到,--host默认0.0.0.0--port默认 9000、--monitor-port默认 9001(兼容旧接口,新接口为--monitor-ports,可传入'{"pull": 8300, "reply": 8400}'形式的 JSON)。控制器启动后,会持续监听 worker 的心跳与上报信息,并将管理 API(如/pin/lookup/clear/move/compress等)暴露在host:port上。

五、第三步:发送推理请求并获取 token 序列

5.1 发送一次 completion 请求

curl -X POST http://localhost:8000/v1/completions \ -H "Content-Type: application/json" \ -d '{ "model": "meta-llama/Llama-3.1-8B-Instruct", "prompt": "Explain the significance of KV cache in language models.", "max_tokens": 10 }'

该请求会让 vLLM 对 prompt 做预填充,LMCache 随即把这段 prompt 对应的 KV cache 分块写入本地 CPU 存储层(LocalCPUBackend)。

5.2 通过 tokenize 接口拿到 token id 序列

curl -X POST http://localhost:8000/tokenize \ -H "Content-Type: application/json" \ -d '{ "model": "meta-llama/Llama-3.1-8B-Instruct", "prompt": "Explain the significance of KV cache in language models." }'

返回结果类似:

{"count":12,"max_model_len":4096,"tokens":[128000,849,21435,279,26431,315,85748,6636,304,4221,4211,13],"token_strs":null}

其中count为 12,说明该 prompt 共 12 个 token(包含起始符128000);tokens数组即完整的 token id 序列,下一步 Pin 操作直接使用这组 id。

六、第四步:调用/pin固定该请求的 KV cache

curl -X POST http://localhost:9000/pin \ -H "Content-Type: application/json" \ -d '{ "tokens": [128000, 849, 21435, 279, 26431, 315, 85748, 6636, 304, 4221, 4211, 13], "instance_id": "lmcache_default_instance", "location": "LocalCPUBackend" }'

三个字段分别对应:

  • tokens:从/tokenize获得的 12 个 token id;
  • instance_id:必须与example.yaml中的lmcache_instance_idlmcache_default_instance)一致;
  • location:KV cache 所在后端,示例为LocalCPUBackend(本地 CPU 存储层)。

成功后会返回:

{"event_id": "xxx", "num_tokens": 12}
  • num_tokens:表示有多少个 token 的 KV cache 被成功固定(此处为 12,与 tokenize 得到的 count 一致);
  • event_id:本次操作的唯一事件 ID,可用于后续查询操作状态(如通过check_finish接口确认异步操作是否完成,参见 控制器 API 服务实现)。

七、源码视角:一次 Pin 操作的完整调用链

Pin 功能并非黑盒,仓库源码清晰地展示了从 HTTP 请求到存储后端的一整条链路:

7.1 HTTP 入口:/pin端点

在 控制器 FastAPI 服务 中,PinRequest定义了请求体(instance_idlocationtokens: list[int]),PinResponse定义返回体(event_idnum_tokens)。处理器会把请求封装为PinMsg并交给LMCacheControllerManager进行编排:

msg = PinMsg(event_id=event_id, instance_id=req.instance_id, location=req.location, tokens=req.tokens) ret_msg = await lmcache_controller_manager.handle_orchestration_message(msg)

PinMsg/PinRetMsg的定义见 消息定义 与 返回消息定义:PinRetMsg包含event_idnum_tokens,对应接口返回的两个字段。

7.2 控制平面:KV Controller 与 Executor

控制器收到PinMsg后,由 KVController.pin 转发给集群执行器(cluster executor):

async def pin(self, msg: PinMsg) -> PinRetMsg: assert self.cluster_executor is not None return await self.cluster_executor.execute("pin", msg)

在 Executor.pin 中,控制器会根据instance_id找到该实例下注册的全部 worker(reg_controller.get_workers),为每个 worker 构造一个PinWorkerMsg,并通过 socket 并行下发,最后汇总各 worker 返回的num_tokens

worker_event_id = f"Worker{worker_id}{msg.event_id}" serialized_msg = msgspec.msgpack.encode( PinWorkerMsg(worker_event_id=worker_event_id, tokens=tokens, location=location) )

如果某个 worker 未注册,控制器会返回ErrorMsg,提示Worker {worker_id} not registered for instance {instance_id}——这也是实践中常见的报错来源(例如instance_id拼写与配置不一致时)。

7.3 数据平面:存储后端的 pin 语义

Pin 最终作用于存储后端中的“内存对象”(MemoryObj)。在 抽象后端接口 中定义了:

@abc.abstractmethod def pin(self, key: CacheEngineKey) -> bool: """Pin a memory object so it will not be evicted."""

对应地,内存对象基类 提供pin()/unpin()抽象方法,其语义注释明确写道:

Pin the memory obj so that it will not be evicted. / Unpin the memory obj so that it can be evicted.

这说明 Pin 的本质是在存储后端与内存管理层共同维护一个“固定标记”:被 pin 的对象在驱逐(eviction)流程中会被跳过,只有 unpin 之后才重新进入可回收集合。unpin/remove等反向操作同样在 抽象后端接口 中有对应定义,可供需要解除固定的场景使用。

7.4 在 MP 模式中的对应能力

若使用 LMCache MP(多进程)模式,Pin 能力由协调器(coordinator)提供,对应 HTTP 接口为 POST/DELETE/GET/cache/pins,相关请求/响应 schema 定义在 coordinator schemas,其中pin_count表示某个 key 上的活跃 pin 数,每次DELETE /cache/pins都会减少一个计数,force参数则允许绕过锁与 pin 过滤器强制删除。官方文档建议新项目优先使用 MP 模式以获得更完善的功能支持与性能(见 LMCache MP 文档)。

八、常见问题与排查建议

现象可能原因排查方向
返回ErrorMsg: Worker not registeredinstance_id与配置不一致,或 worker 尚未上报核对example.yaml中的lmcache_instance_id;确认controller_pull_url(9001)可达
num_tokens为 0该 token 序列的 KV cache 尚未写入指定location先发送一次 completion 请求再执行 Pin;确认local_cpu: True且容量充足
控制器端口连不上控制器未启动或端口被占用确认lmcache_controller正常运行,--port/--monitor-port与配置对应
无法通过 9001 上报controller_pull_url与控制器 monitor 端口不一致两者必须都是localhost:9001

此外还需注意:tokens必须是 vLLM 使用的真实 token id 序列(建议直接复用/tokenize的输出,避免手工分词产生偏差);location名称应与实际存储后端一致,不同后端(如LocalCPUBackend、远端存储等)的命名以当前仓库配置与实现为准。

九、总结

通过本示例你可以看到,LMCache 的 Pin/Persistence 能力让 KV cache 的管理不再局限于推理引擎内部:外部系统可以通过控制器暴露的/pinHTTP 接口,精确到 token 粒度地指定哪些 KV cache 需要长期保留。这在热 prompt 预加载、多请求共享前缀缓存、以及缓存预热等场景中非常实用。

整套流程的核心在于“实例 ID + 位置 + token 序列”三者对齐:instance_id决定命中哪个实例,location决定作用于哪个存储层,tokens决定固定哪些 chunk。配合 example.yaml 与本文的调用链分析,你可以直接在自己的环境中复现这一流程,并将 Pin 集成到业务侧的缓存管理逻辑中。若想进一步了解控制器暴露的其他管理接口(lookup、clear、move、compress 等),可继续阅读 控制器内部 API 服务 与 KV cache 管理文档。

【免费下载链接】LMCacheLMCache: Supercharge Your LLM with the Fastest KV Cache Layer项目地址: https://gitcode.com/GitHub_Trending/lm/LMCache

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询