if not redis.set(f'lock:{key}', 1, nx=True, ex=10):
time.sleep(0.05)
else:
data = load_from_db(key)
redis.set(key, data, ex=600)
爆款商品缓存到期的那几秒,数据库连接数突然打满,接口大面积超时。这类现象通常不是突然出现的,往前翻半天日志能看到苗头。
追下去是这么回事:热点键失效瞬间没有兜底,所有请求同时回源重建缓存。
围绕「缓存击穿」排查时,命令行跑一遍比在面板里点十次有用,面板会替你做掉不少隐式操作。监控和日志的时间要对上,时区不一致会多绕很大一圈。
临时改动用注释写上日期和原因,过两周自己都记不清为什么这么写。动手前把原文件复制一份带时间戳,出问题立刻换回去,比现场分析快得多。
一次只改一处,改完立刻验证,几个改动叠在一起,出问题就说不清是谁导致的。先做最小复现,能稳定跑出来的问题,排查成本会低一个数量级。
处理上按这个顺序:加互斥锁只放一个请求回源;热点数据设置不过期并后台刷新;空结果也做短期缓存。
确认没问题再收工,缓存到期时数据库压力平稳,接口无超时。