大语言模型推理中的缓存策略设计踩坑记录
最近在为一个大语言模型推理服务做性能优化,踩了不少坑,特别想分享一下缓存策略设计中的一些血泪史。
问题背景
我们部署了一个基于Transformer的LLM服务,QPS达到1000+,但发现推理延迟居高不下。通过分析发现,大量重复的前缀处理成了性能瓶颈。
我的错误实践
最初我尝试了最简单的LRU缓存策略,代码如下:
from collections import OrderedDict
class LRUCache:
def __init__(self, capacity):
self.capacity = capacity
self.cache = OrderedDict()
def get(self, key):
if key in self.cache:
self.cache.move_to_end(key)
return self.cache[key]
return None
def put(self, key, value):
if key in self.cache:
self.cache.move_to_end(key)
elif len(self.cache) >= self.capacity:
self.cache.popitem(last=False)
self.cache[key] = value
但问题来了:
- 缓存键设计错误 - 我直接用完整的prompt作为key,导致大量相似的前缀被重复缓存
- 过期策略混乱 - 没有设置合理的TTL,缓存堆积严重
- 并发控制缺失 - 多线程下出现竞态条件
正确的解决方案
最终我们采用分层缓存策略:
import asyncio
from cachetools import TTLCache
from typing import Dict, List
# 1. 前缀缓存(L1)
class PrefixCache:
def __init__(self, maxsize=1000, ttl=300):
self.cache = TTLCache(maxsize, ttl)
def get_prefix(self, prefix_key: str) -> Dict:
return self.cache.get(prefix_key)
def set_prefix(self, prefix_key: str, value: Dict):
self.cache[prefix_key] = value
# 2. 完整缓存(L2)
class FullCache:
def __init__(self, maxsize=10000, ttl=600):
self.cache = TTLCache(maxsize, ttl)
def get_full(self, full_key: str) -> Dict:
return self.cache.get(full_key)
def set_full(self, full_key: str, value: Dict):
self.cache[full_key] = value
关键改进点:
- 分层缓存 - 前缀用短TTL,完整请求用长TTL
- 智能键设计 - 前缀提取+哈希处理避免重复
- 并发安全 - 加锁机制防止竞态条件
实际效果
优化后延迟从平均150ms降到80ms,QPS提升约30%。
总结
缓存不是简单的数据存储,需要考虑键设计、过期策略和并发控制。别像我一样踩坑!

讨论