现场是这样的。问答服务用 Redis 存语义缓存,key 是问题向量、value 是答案,三天后内存从 3GB 涨到 40GB,maxmemory 打满开始淘汰,命中率跟着掉。

中间走过弯路,把「相似问题各自成 key,没有做合并」当成主因,改完现象没变。

把日志和配置对完,能解释这个现象的基本就这几处。向量以 JSON 数组存,一个 key 占十几 KB;没有设置 TTL,历史问题只增不减;答案里带整段原文,单条 value 超过 20KB。

先抽样看几个 key 的实际内存占用

redis-cli --bigkeys

然后统计 key 数量与前缀分布

redis-cli --scan --pattern 'sem:*' | wc -l

随后改成二进制存向量并压缩答案

python -c "import numpy as np,redis;r=redis.Redis();r.set('sem:demo',np.zeros(1536,dtype=np.float32).tobytes())"

给缓存加 7 天 TTL 并限制单条大小

python sem_cache.py --ttl 604800 --max-value 4096

别只看报错消失,验证要多做一步。同样流量下内存稳定在 6GB 以内,bigkeys 里不再出现超大 key,命中率维持在原有水平。

提醒一点。向量缓存的内存大头往往不是向量本身而是 JSON 序列化和长答案,改二进制加 TTL 两步就能把占用压下一个量级。同一份配置在测试环境跑通,不代表线上没事,两边的默认值经常不一样。

作者 9823189