现场是这样的。服务部署了 4 个 Pod,每个进程里用 cachetools 的 TTLCache 缓存租户配置,TTL 设了 600 秒,运营改完配置后连续刷新页面,四次请求返回了新旧三种内容,日志显示每个 Pod 的写入时间不同。
中间走过弯路,把「配置变更没有广播机制,其他副本只能等过期」当成主因,改完现象没变。
排查方向其实有限,先把可能性排一排。本地缓存各存一份,更新只打到其中一个 Pod;TTL 到期时间按进程启动时间错开,回收节奏不一致;负载均衡按连接保持,同一用户短时间内落到同一 Pod 看不出问题。
上来先确认四个副本缓存的值是否不同
for p in $(kubectl get pod -l app=cfg -o name); do kubectl exec $p -- curl -s localhost:8000/debug/cache; done
随后把本地的值和新配置对比
python -c "print({'pod_a':'v11','pod_b':'v10'})"
再往下改成变更时发布失效消息
redis-cli publish cfg:invalidate 'tenant:8821'
或直接去掉本地缓存只留 Redis
python -c "print('drop TTLCache, read through redis')"
别只看报错消失,验证要多做一步。四个副本在同一秒内都返回新配置,连续刷新十次结果一致,配置变更的生效延迟控制在一秒以内。
本地缓存省下的那点延迟,换来的是一致性排查成本,多副本场景要么加广播失效,要么干脆不缓存。线上能稳定复现的问题都不算难,难的是只在大流量下才出现的那种。
