记录一下那天晚上的排查过程。搜索入口的 query embedding 每次都重新算,热门词一天被调用 9 万次,向量服务账单里 40% 来自完全相同的输入。

刚开始盯着「大小写和空格没有归一,同一句被当成不同 query」,折腾了半个多小时,排掉了。

这类报错背后常见的原因有几处,逐个排除就行。查询侧没有对 embedding 结果做缓存。少数情况下是缓存键带了时间戳,永远不命中。

少数情况下是缓存 TTL 只有 60 秒,热点词反复过期。

上来先统计 query 的重复率

python -c "import json,collections;d=[json.loads(l)['q'] for l in open('q.jsonl')];c=collections.Counter(d);print(sum(1 for v in c.values() if v>1), len(c))"

缓存键只保留归一化后的 query 与模型名

python -c "import hashlib;print(hashlib.md5('退款流程 bge-m3'.encode()).hexdigest())"

接着把 TTL 按热点程度分档

python -c "print({'hot_ttl_s':86400,'cold_ttl_s':600})"

末了对比开启缓存前后的调用量

python cost_report.py --group-by provider --since 3d

改完先别撤,确认这几项。embedding 调用量下降 62%,热门词命中率达到 88%,检索结果与直算完全一致。

embedding 是纯函数,同样的输入没必要算第二次;缓存键一定要归一化,带时间戳的键等于没有缓存。线上能稳定复现的问题都不算难,难的是只在大流量下才出现的那种。

作者 9823189