先把当时的情况摆出来。缓存 value 里直接 pickle 了 pydantic 对象,升级到 2.5 后反序列化报 Can't get attribute Answer on module app.models,命中缓存的请求全部 500。
排查方向其实有限,先把可能性排一排。pickle 依赖类的模块路径 改名即失效。另一种情况是新旧版本的类定义互不兼容。
少数情况下是缓存里混了多个版本的对象。不容易想到的是,key 上没有版本前缀 无法区分。
动手时先找出无法反序列化的 key
redis-cli --scan --pattern 'llm:*' | head -20
缓存改成存 JSON 再反序列化
python -c "import json;print(json.dumps({'a':1}))"
key 加 schema 版本前缀
python patch_cache.py --prefix 'llm:v2:'
等前面都确认过,再启动时清理旧前缀并灰度验证
python cache_migrate.py --drop-prefix 'llm:v1:'
这台环境是别人交接的,不少默认值被动过,只能一项项核。
同事提醒我看一下最近一次发布,时间点确实对得上。
别只看报错消失,验证要多做一步。命中旧缓存的请求不再 500,反序列化全部成功,缓存命中率在灰度后恢复。
容易忽略的是,缓存里存对象就把部署和数据结构绑死了,存 JSON 是更省心的选择。拖得越久,排查成本越高,因为现场状态会被后续操作覆盖。
