结论:别混用 functools.lru_cache 和 redis 做同一层缓存——它们解决的是完全不同的问题,强行组合反而增加复杂度和一致性风险。

直接说结论:别混用 functools.lru_cache 和 Redis 做同一层缓存——它们解决的是完全不同的问题,强行组合反而增加复杂度和一致性风险。
什么时候该用 lru_cache,而不是 Redis
它只适合单进程内、纯计算型、参数可哈希、无副作用的函数。比如解析固定 JSON Schema、计算斐波那契、校验 token 签名(密钥不变时)。
-
maxsize=128是合理起点;设为None容易内存失控,尤其参数是长字符串或嵌套 tuple 时 - 函数不能依赖外部状态(如全局变量、数据库连接、
datetime.now()),否则缓存结果会“看起来对、实际错” - 多线程安全,但多进程不共享——Flask 多 worker 或 FastAPI uvicorn 多进程下,每个进程都有独立缓存,无法协同失效
- 不支持 TTL,也不能手动删某个 key,只能全清:
func.cache_clear()
什么时候必须上 Redis,绕不开
需要跨进程/跨机器共享、带过期时间、支持主动失效、或缓存数据本身不可哈希(比如含 list、dict、自定义对象)时,lru_cache 就失效了。
仅使用 Python 将 Claw Code 虚拟化框架与 OpenClaw 集成,提供 184 种工具和 200 多条命令,用于安全分析和代码质量...
- 用
redis-py写入时务必加ex参数,例如r.set("user:1001", json.dumps(data), ex=300),否则缓存永不过期 - 避免把整个大对象(如 10MB 的 pandas DataFrame)直存 Redis,先压缩或只存关键字段+查库逻辑
- Redis 连接要复用,别每次
redis.Redis()新建实例;用连接池(ConnectionPool)更稳 - 注意序列化方式:
json兼容性好但不支持datetime;pickle快但有反序列化风险,生产环境慎用
真要组合用,只在分层场景下有意义
比如:第一层用 lru_cache 挡住同进程内高频重复调用(如模板渲染中反复调用的 format_price()),第二层用 Redis 挡住跨请求/跨实例的重复查询(如用户资料 GET /api/user/123)。
- 两层之间不要自动同步——
lru_cache不知道 Redis 删了 key,Redis 也不管进程内缓存是否脏 - 写操作(如更新用户昵称)必须同时触发:DB 更新 → Redis 删除(
DEL user:123)→ 本地lru_cache清理(如果能定位到对应函数,调func.cache_clear()或按需重置) - 读操作走“先查本地
lru_cache→ 命中则返回 → 不命中再查 Redis → Redis 不命中才查 DB + 回填 Redis + 可选回填本地缓存”
容易被忽略的关键点
缓存键的设计比存储方式更重要。同一个业务逻辑,键里漏了版本号、环境标识或 tenant_id,上线后就可能跨租户返回错误数据。
- 别用原始请求参数拼 key,比如
f"user:{user_id}"要比f"user:{request.args}"可靠得多 - Redis 中用
HSET存结构化数据(如用户信息)比多个SET更省 key 数量,但得自己处理字段级更新 -
lru_cache的typed=True参数常被忽略:它会让1和1.0视为不同参数,多数场景应关掉 - 本地缓存(dict 或 lru_cache)和 Redis 同时存在时,最危险的不是性能差,而是“你以为删了,其实只删了一半”
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










