本地缓存与redis是分层协作关系,非二选一:本地缓存仅存极热、静态或小体积元数据(如配置、top商品id、停用词表),redis承担中心化一致缓存,共同构成local→redis→db三级漏斗。

本地缓存和Redis缓存不是二选一,而是分层协作
直接用本地缓存(比如Python的dict或lru_cache)扛高频查询,短期快,但多实例部署时数据不一致、无法共享、扩容后缓存全失效——这在Web服务里等于埋雷。真正靠谱的做法是:本地缓存只存“极热”数据(如全局配置、TOP 10商品ID),Redis作为中心缓存承载95%的重复请求。两者不是替代关系,是local → Redis → DB三级漏斗。
本地缓存该缓什么?别碰业务实体
本地缓存空间有限,且重启即丢,所以只适合放三类东西:
- 静态不变或极少变的元数据,比如
sentiment_labels = {"POS": 1, "NEU": 0, "NEG": -1} - 高频访问但体积小的键值对,比如
config:timeout对应的数值300 - 模型推理前的预处理规则,比如中文分词停用词表(加载一次,复用全程)
千万别把用户评论原文、StructBERT输出结果这类业务数据塞进本地缓存——它们变化频繁、体积大、跨进程不可见,反而会放大脏数据风险。
本地缓存怎么设过期?别依赖TTL
Python的@lru_cache(maxsize=128)不支持TTL,functools.cache也不行。硬加时间判断又破坏简洁性。更务实的做法是:
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
- 用
cachetools.TTLCache,显式指定ttl=60(秒),它会在get时自动检查过期 - 避免用
time.time()手写时间戳比对——时钟漂移、线程安全都得自己兜底 - 本地缓存不设永不过期;哪怕只是
ttl=300,也能防止冷启动后旧数据长期滞留
注意:cachetools的TTLCache不是线程安全的,Web服务多线程场景下要包一层threading.Lock,或者改用LRUCache + 主动刷新机制。
本地缓存命中后,还要查Redis吗?看一致性要求
如果本地缓存只是辅助加速(比如加速日志采样率计算),那完全可跳过Redis;但如果涉及用户状态、库存、情感分类结果等需要强一致性的数据,必须走Redis这一层——本地缓存只是“提前猜中”,最终结果仍以Redis为准。
典型做法是:先查本地缓存(快路径),命中则记录hit_local指标;再同步查Redis,若Redis返回不同值,就用Redis结果覆盖本地缓存,并触发一次cache.refresh事件。这种“本地+中心”双检模式,在GTE-large部署中实测能把QPS稳定撑到120+,同时保证99.98%的响应延迟
最容易被忽略的是:本地缓存的key命名没加版本号。比如sentiment:result:good在模型升级后语义变了,但本地缓存还拿着旧结果——必须把模型哈希(如model_v2_sha256[:8])嵌进key里,否则缓存越久,错得越稳。










