
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 实例标识locationKV cache 所在的存储位置后端tokens要固定的 token id 序列返回event_id操作事件 ID与num_tokens被固定下来的 token 数。这与“移动move”“压缩compress”“清理clear”等操作一起构成了 LMCache 控制器对外提供的 KV cache 管理能力集合相关接口在 控制器 KV 控制器实现 中均有对应实现。二、环境准备与端口规划开始之前请确认以下前提至少 1 张 GPU示例使用CUDA_VISIBLE_DEVICES0指定端口规划如下端口服务说明8000vLLM 推理服务接收推理请求与 tokenize 请求8001LMCache worker在example.yaml中通过lmcache_worker_ports配置9000LMCache 控制器提供/pin等管理 API9001控制器 monitorpull 端口控制器拉取 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: 256KV cache 分块大小token 数LMCache 以 chunk 为粒度存储与检索 KV cachelocal_cpu: True与max_local_cpu_size: 5启用本地 CPU 内存作为 L2 存储容量上限为 5GBPin 操作的目标位置LocalCPUBackend即指这一层enable_controller: True开启缓存控制器使其能够接收外部的/pin等管理指令lmcache_instance_id: lmcache_default_instance实例 ID后续调用/pin时instance_id字段必须与此一致controller_pull_url: localhost:9001worker 上报给控制器的地址对应控制器的 monitor 端口 9001lmcache_worker_ports: 8001LMCache worker 监听端口p2p_host: localhost、p2p_init_ports: 8200节点间 P2P 通信如跨实例共享的标识信息。四、第二步启动 vLLM 引擎与 LMCache 控制器4.1 启动 vLLM 引擎端口 8000CUDA_VISIBLE_DEVICES0 LMCACHE_CONFIG_FILEexample.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_FILEexample.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 控制器端口 9000monitor 端口 9001lmcache_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包含起始符128000tokens数组即完整的 token id 序列下一步 Pin 操作直接使用这组 id。六、第四步调用/pin固定该请求的 KV cachecurl -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 idinstance_id必须与example.yaml中的lmcache_instance_idlmcache_default_instance一致locationKV 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_id、location、tokens: list[int]PinResponse定义返回体event_id、num_tokens。处理器会把请求封装为PinMsg并交给LMCacheControllerManager进行编排msg PinMsg(event_idevent_id, instance_idreq.instance_id, locationreq.location, tokensreq.tokens) ret_msg await lmcache_controller_manager.handle_orchestration_message(msg)PinMsg/PinRetMsg的定义见 消息定义 与 返回消息定义PinRetMsg包含event_id与num_tokens对应接口返回的两个字段。7.2 控制平面KV Controller 与 Executor控制器收到PinMsg后由 KVController.pin 转发给集群执行器cluster executorasync 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找到该实例下注册的全部 workerreg_controller.get_workers为每个 worker 构造一个PinWorkerMsg并通过 socket 并行下发最后汇总各 worker 返回的num_tokensworker_event_id fWorker{worker_id}{msg.event_id} serialized_msg msgspec.msgpack.encode( PinWorkerMsg(worker_event_idworker_event_id, tokenstokens, locationlocation) )如果某个 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_url9001可达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),仅供参考