跳至正文
-
关注
IT极限技术分享汇

ITmax

IT极限技术分享汇

ITmax

  • 首页
  • 商店
  • 我的帐户
  • 结账
  • 购物车
  • 首页
  • 商店
  • 我的帐户
  • 结账
  • 购物车
关

搜索

LMCache 封面图:GitHub 12,272 星,官方基准 TTFT 降 75%,近四周 311 次提交
技术分享

vLLM 一重启缓存就失忆|LMCache 把 KV cache 搬出进程外,这笔账我替你算过

mumupudding 的头像
作者 mumupudding
2026年11月4日 3 分钟阅读
0

vLLM 一重启缓存就失忆|LMCache 把 KV cache 搬出进程外,这笔账我替你算过

LMCache 封面图:GitHub 12,272 星,官方基准 TTFT 降 75%,近四周 311 次提交
LMCache:给大模型推理加一层的 KV cache 管理层,Apache-2.0 开源,vLLM 生态之外还支持 SGLang 与多家硬件

我的 GPU 在给同一段话反复买单

先交代一个我自己身上真实存在的场景。之前搭知识库问答,我把几万字的内部文档切成背景材料塞进 system prompt,再拼上用户问题发给推理服务。那时候我还没意识到问题出在哪,只是纳闷:同样的背景材料,一小时内被几百个请求各算了一遍,GPU 利用率看着挺饱满,真正”生成”的时间却不多。后来弄明白 prefill 和 decode 的区别才回过神来——那些重复的前缀,每一遍都在烧钱。

vLLM 其实自带一招:automatic prefix caching(APC),相同前缀命中就直接复用显存里的 KV cache。听起来够用了?我用下来(准确说,是我盯着别人的运维记录和 issue 看下来)有两个硬伤绕不过去。第一,这个缓存住在 vLLM 进程自己肚子里,进程一重启,全部失忆,所有请求从头 prefill,高峰期重启一次就是一场雪崩。第二,它只认”前缀”,从第一个 token 开始严格匹配;多轮对话里每轮追加的内容、RAG 里检索块插在中间的场景,全都不命中。我翻到有同行算过一笔账:一个两万 token 长文档的问答服务,文档部分的 prefill 计算被成千上万个请求重复支付——这些 GPU 时间,本来一分都不用花。

LMCache 就是冲着这两刀来的。它把 KV cache 从推理进程里搬出来,落到 CPU 内存、本地 SSD、Redis、Mooncake、S3 这些层级里,做成可以跨请求、跨实例、甚至跨引擎复用的资产。开源在 GitHub 上,Apache-2.0 协议,2024 年 5 月建仓,现在已经进了 PyTorch Foundation 生态,NVIDIA 的 Dynamo 推理框架也把它列为集成的缓存层。我第一眼看到”KV cache 管理层”这个定位时的反应是:这不就是给推理服务加了个 Redis 吗?把文档和 issue 读完之后我承认,事情没那么简单,但坑也没那么少。

它干的事,是把消耗品变成资产

我把它的能力拆成四组,顺便说说哪几组是真本事。

第一组:分层存储加跨请求复用,这是命根子。 KV cache 算完之后不再只住在显存里,而是按 GPU 显存 → CPU 内存 → 本地 SSD → 远端存储(Redis/Valkey、Mooncake、InfiniStore、S3 兼容对象存储)分级下沉,命中时再装回来。官方文档里有个对体感很有用的数字:Qwen3-8B 这个模型,1GB 的 KV cache 大约对应 46,020 个 token(这是官方 benchmark 配置里给出的换算值)。也就是说一份 2 万 token 的长文档前缀,KV 大概半 GB 上下,CPU 内存轻松装下几十份。官方 benchmark 页用 Qwen3-8B 跑了一组长文档问答对比:46 个请求,裸 vLLM 平均首 token 延迟 757 毫秒,挂上 LMCache 之后 185 毫秒,降了 75%;整个基准的耗时从 23.47 秒缩到 13.79 秒。原因文档也讲得直白:裸 vLLM 的工作集一旦超出显存里的 KV 空间,第二轮就得全部重算前缀,而 LMCache 把被挤出的块留在 CPU 内存里按需恢复。

第二组:独立守护进程,引擎崩了缓存不陪葬。 这就是它主推的 MP(multiprocess)模式:LMCache 自己跑成一个独立 server,vLLM 通过 connector 跟它握手。vLLM 崩溃、重启、滚动更新,缓存都在 LMCache 那边活着,新实例起来直接接着用。我判断这一组是真有东西的:重启失忆是所有进程内缓存方案的通病,把缓存生命周期跟引擎解耦,价值在滚动更新频繁的生产环境里会被反复兑现。代价当然也有,后面单独算。

第三组:非前缀复用 CacheBlend,最亮眼但要冷静看。 传统前缀缓存要求 token 序列从头严格匹配,CacheBlend 允许复用 prompt 中间任意位置的缓存块,只对拼接处少量重算来恢复质量。这对 RAG(检索块每次插的位置都不同)和多轮对话(中间夹着动态工具结果)是理论上的大杀器。但我要泼的冷水是:这是论文转化来的特性,生产环境里大规模验证的公开记录还不多,官方文档自己也没把它列为默认路径。我会把它当”值得关注”而不是”可以依赖”。

第四组:可观测性,意外地扎实。 缓存命中率(请求级和 token 级)、各层读写耗时、缓存容量、淘汰情况,Prometheus 指标齐全。缓存系统没有指标就是盲开,这一点它比很多同类项目做得诚实。

还有一块要提一下没那么光鲜:SGLang 的集成目前只有 MP 模式,得单独起一个 lmcache/standalone 容器再开 --enable-lmcache;prefill 和 decode 分离(PD disaggregation)那条路要 NIXL 加 RDMA 或 NVLink 的传输环境,普通单机玩家碰不到也不用碰。我的建议是:先把 vLLM 加 MP 模式这一条主路走通,别的当地图标记就好。

独立进程这笔账,收益和利息都要认

LMCache 的架构选择,我认为一句话就能概括:把 KV cache 从”进程内的临时状态”升级成”进程外的持久资产”。聪明在哪已经说过了,现在算利息。

第一笔利息是传输和序列化本身要钱。KV cache 从引擎搬到 LMCache 再搬回来,每一趟都是实打实的序列化、网络传输、反序列化。仓库里有个最近开的高质量 issue(#5440)把这个代价量化了:在 PCIe 主机上,MP 模式下每个传输对象有大约 0.55 秒的固定开销,线上的传输时间反而被这个固定成本淹没——注意这是他们在用 pickle 传输的场景下测的,官方已经认了这个问题在跟进。换句话说,缓存命中省下的 prefill 时间,可能被搬运的固定开销吃掉一大块,短 prompt 场景甚至倒贴。

第二笔利息是兼容性的复杂度。官方专门写了一整页兼容性文档,把”能不能一起跑”拆成三层:Python/PyTorch/CUDA 的 ABI 要对上;vLLM 版本要能加载你要的那个 connector(vLLM 0.20.0 之前只能用它内置的实现,之后才能显式指定 LMCache 自带的模块路径);具体模型还要看有没有对应的验证记录——文档里写明 GLM-5.2 是在 vLLM 0.23.0 加 LMCache 0.4.7 这个精确组合下验证的,Kimi K3 要 0.5.3 以上。这套现实意味着”装个最新版就完事了”在这里行不通,升级前要对着矩阵核一遍。我不太喜欢这种复杂度,但转念一想,一个要碰底层显存布局和原生扩展的缓存层,兼容性问题不是它能选择的,是它注定要背的。

我的反对意见也给单实例玩家:如果你的服务只有一个 vLLM 实例、几乎不重启、prompt 又全是短文本,vLLM 自带的 APC 就够了,引入 LMCache 纯属给自己加运维面。这东西的价值密度跟”重启频率 × 多实例数 × prompt 重复度”成正比,三个都低就别折腾。

安装这一关,官方文档写得很老实

先把丑话说在前面:官方没有给出整机级别的内存或磁盘门槛表,下面两档里标”官方”的我都注明了出处,标”我按文档和 issue 推的”就是推算,别当成官方口径。

官方明确写的要求(来自安装文档原文):Linux,Python 3.10 到 3.14,NVIDIA GPU 算力 7.0 起(也就是 Volta 往后),CUDA 12.1 以上;AMD ROCm(MI300X/MI350X 系列)、Intel XPU、摩尔线程 MUSA 这些非 N 卡通道也各有发布版,昨天(11 月 3 日)还在发 v0.5.7rc4 的 xpu、rocm、musa、rbln 多路构建。

最低可用档(我的推算):单张 24GB 显存的卡(4090、3090 这一级)加 64GB 系统内存,够跑 Qwen3-8B 这类 8B 模型加一个进程内(in-process)模式的 LMCache,CPU 侧留 20GB 给缓存就有效果。建议档(我的推算,参考官方 MP 示例):生产上走 MP 模式,官方 benchmark 示例里 L1 缓存直接给了 66GB,再加上模型本体和 vLLM 的开销,128GB 内存、一张 A100/H100 或双 4090 是比较舒服的位置;磁盘层要开的话,按上面 46,020 token/GB 的换算自己估容量。

安装本身倒是丝滑,官方推荐用 uv:

uv venv --python 3.12
source .venv/bin/activate
uv pip install lmcache vllm

验证装没装对,官方给了一行:

python -c "import lmcache.cuda_ops"

不想碰 CUDA 的还有个取巧路线:pip install lmcache-cli,只装命令行工具(跟主包是同一个 lmcache 命令,官方提醒别两个一起装),可以先把 server 和 benchmark 工具摸熟。要我推荐的话,最省心的是直接上官方 Docker 镜像,vLLM 和 LMCache 的版本在里面是配好对的:

docker pull lmcache/vllm-openai

镜像默认用非 root 的 lmcache 用户跑,HF 模型缓存要挂到 /home/lmcache/.cache/huggingface,这个细节官方文档写了但很容易漏,漏了的症状就是容器里下不动模型。

上手跑一遍:官方这条最小链路,我逐行对过

先诚实交代:我手上没有能跑 CUDA 的机器,这一节我没法写真跑的输出,下面的命令和日志全部逐条来自官方 quickstart 文档,我核对过的是命令之间的依赖关系和参数含义。想抄作业的可以直接照走。

最快见效的是进程内模式,一条命令起服务:

LMCACHE_CHUNK_SIZE=8 \
vllm serve Qwen/Qwen3-8B \
    --port 8000 --kv-transfer-config \
    '{"kv_connector":"LMCacheConnectorV1", "kv_role":"kv_both"}'

(chunk size 设成 8 只是官方为了用短 prompt 也能看到缓存动静,生产保持默认 256。)

然后用同一个前缀连打两次:

curl http://localhost:8000/v1/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "Qwen/Qwen3-8B",
    "prompt": "Qwen3 is the latest generation of large language models in Qwen series, offering a comprehensive suite of dense and mixture-of-experts",
    "max_tokens": 100,
    "temperature": 0.7
  }'

官方文档给出的预期日志是这样的:第一次请求缓存是空的,逐块写入(Stored 16 tokens in 0.023 seconds 这一类的输出);第二次请求就能看到命中——32 个 token 的 prompt 里命中 24 个(其中 16 个来自 vLLM 自己的 GPU 前缀缓存,8 个由 LMCache 从 CPU 内存补上),日志里会有 Retrieved 8 out of 24 required tokens ... cost 0.55 ms, throughput: 1.98 GB/s 这样的行。看到这个输出,链路就算通了。

要走 MP 模式的话多一步,先起独立 server:

lmcache server \
    --host localhost --port 5555 \
    --l1-size-gb 20 --eviction-policy LRU --chunk-size 16

再把 vLLM 的 connector 换成 LMCacheMPConnector 并指到 5555 端口。一个容易翻车的细节:vLLM 0.20.0 以下加载不到 LMCache 自带的 connector 实现,版本对不上时要么升级 vLLM,要么显式加 kv_connector_module_path 指到 lmcache.integration.vllm.lmcache_mp_connector——官方兼容性页的原话是,不加这个路径,vLLM 可能静默选中一个协议更旧的内置 connector,然后你就开始排查为什么功能对不上。

别人踩过的坑,我一条条对过

issue 池子不小(开放中的有 909 个),我把高频的和近期的用户报错类都过了一遍,再交叉搜了第三方实测,挑五条值得记的。

第一,异常退出后重启卡死。 #5265 记录了一个很刁的场景:vLLM 的 worker 异常退出后,残留的 CUDA IPC 映射会挡住下一次 vLLM 重启。这类问题在 MP 模式引入共享内存传输后概率变高,症状是进程退了但资源没放干净,只能手动清理。生产上建议给重启流程留一个”确认无残留”的检查步骤。

第二,GPU 上下文丢失后的内存泄漏。 #5270:MP 客户端发出去了但没人应答的 STORE/RETRIEVE 请求,在 GPU context 丢失之后会在客户端侧无限堆积。这个 issue 目前还开着,也就是说没有彻底修复,GPU 出过故障的机器上要留意内存曲线。

第三,静默返回坏的缓存。 #5344 是我最警惕的一个:批量分配 L1 失败时会提交一个”撕裂”的 TP 前缀,之后 retrieve 不报错,直接把损坏的 KV 返回给你。不报错的坏数据比报错可怕十倍,如果你的服务出现”莫名其妙的输出质量下降”,值得把缓存命中率日志和引擎日志对一下时间线。

第四,PCIe 主机上的固定搬运开销。 前面提过的 #5440,每个传输对象约 0.55 秒固定成本,pickle 传输场景。NVLink 机器没这个问题,PCIe 单机用户在 MP 模式下要对”命中收益减固定开销”有心理准备。

第五,磁盘层的持久化没那么稳。 #1175 早在讲 SSD offloading 的缓存持久化问题;第三方也有实锤——kubesimplify 那篇实测(作者在一台统一内存的 ARM 机器上连测三个版本配对)里,磁盘持久化路径”写入成功,但重启后找不到”,作者自己都把这标记成实验结论而不是推荐配置。

第三方体验里还有两条我认可度高的:learncode.college 那篇把”什么人别用”讲得很透,作者试过给一个文档摘要工具挂缓存,命中率只有 3%,网络和序列化开销反而让延迟涨了 15%;MindStudio 的对比文章则提醒 MP 模式下 vLLM 重启时缓存进程的内存释放有延迟。共同指向一个结论:这工具的收益完全由负载特征决定,上之前先拿真实 prompt 证明重复度,别看 star 数头脑发热。

我最后的判断

值不值得上手,我的判断标准就三问:你的服务重启频繁吗?实例不止一个吗?prompt 里有大段重复内容(长 system prompt、固定模板、共享文档)吗?三个里中了两个,LMCache 就是正收益,官方基准里 75% 的 TTFT 降幅和跨重启复用都是真金白银;三个全不沾,回去把 vLLM 的 APC 打开就好,别给自己加一层要维护的分布式系统。

替代方案我说两个。第一个是 vLLM 内置 APC:零运维、默认就该开,输在进程内(重启失忆)、仅前缀匹配、实例之间不共享——它跟 LMCache 不是二选一,官方链路里两者是叠着用的(GPU 内命中归 APC,CPU 层补位归 LMCache)。第二个是 SGLang 加 RadixAttention:引擎内的基数树缓存,多轮对话的分支复用做得很优雅,如果你的栈本来就愿意整体迁到 SGLang,它自带的缓存体系能覆盖大部分单机需求;但它同样活在进程里,跨引擎复用和持久化层级就是 LMCache 的主场了。我的排序很简单:单引擎单机先榨干引擎自带能力,多实例、要持久、跨引擎,再请 LMCache 出山。

最后说句实在的,这个项目不是我日常会装在自己笔记本上的那种玩具,而是一层明确属于生产推理架构的基础设施。顺手拉了下,现在是 12,272 个 star,最近四周 311 次提交,稳定版 0.5.6,昨天还在一口气发 0.5.7rc4 的五种硬件构建——维护强度和生态站位都在那,唯一的问题是你的负载配不配得上它。

mumupudding 的头像
作者

mumupudding

关注我
其他文章
Hermes Agent 封面:259873 个 star,最新版本 v0.22.6,近四周 10508 次提交,会自己长技能的开源管家
上一个

别的助手用完就忘|Hermes Agent 自己攒技能自己长记性,25.9 万 star 我先拆了它的安装脚本

暂无评论!成为第一个。

发表回复 取消回复

您的邮箱地址不会被公开。 必填项已用 * 标注

Copyright 2026 — IT极限技术分享汇. 备案号:浙ICP备17006560号-2