缓存雪崩是成千上万个缓存项同一秒批量过期导致数据库压力骤增,需通过设置随机过期时间、启用互斥锁、分层预热+双key容灾及关闭调试模式四步解决。

ThinkPHP5项目在高并发场景下突然响应变慢、数据库连接数飙升、页面大量报500错误——这极大概率是缓存雪崩引发的连锁故障。它不是个别缓存失效,而是成千上万个缓存项在同一秒批量过期,所有请求瞬间穿透到数据库。
为缓存键设置随机过期时间
打开业务逻辑中调用Cache::set()或cache()函数的位置。
将原本固定的缓存时间(如3600)替换为带随机偏移的值:$expire = 3600 + rand(60, 600)。
这一步必须在所有高频缓存写入处统一修改,【否则部分缓存仍会集体失效】。
若使用Redis驱动,确保其底层未开启key自动对齐策略(如Redis 7.0+的active-defrag-ignore-bytes默认值可能干扰随机性)。
启用互斥锁防止缓存重建风暴
方法一:用ThinkPHP原生锁机制
在获取缓存失败后、查询数据库前,插入锁校验:$lockKey = 'lock_'.$cacheKey;if (Cache::store('redis')->inc($lockKey) === 1) { Cache::store('redis')->expire($lockKey, 10); } else { usleep(50000); goto retry; }。
方法二:改用setnx原子操作(推荐)
直接调用Redis命令:$redis->setEx($lockKey, 10, 'building') === false时,说明已有进程在构建,当前请求等待100ms后重试;返回true则执行数据库查询→写缓存→删锁。
注意:锁超时时间必须短于缓存本身TTL,否则可能造成缓存长期不更新。
分层预热+双Key容灾
第一步:在每日低峰期(如凌晨3点)执行预热脚本,加载TOP100热点数据并设置长TTL(如7200秒)。
第二步:对关键业务缓存同时写入两个key——主key(user:1001:profile,TTL=3600)和备用key(user:1001:profile:bak,TTL=14400)。
第三步:读取时先查主key,若为空则立即读备用key,并异步触发重建主key任务。
第四步:在crontab中每15分钟执行一次备用key刷新,确保其始终比主key多存活至少2小时。
这一步操作起来很简单,直接把预热脚本丢进定时任务就行。
强制关闭调试模式并清空旧缓存
确认config/app.php中'app_debug' => false已生效。
检查.env文件是否存在APP_DEBUG=true且未被注释,如有则删除该行或改为false。
执行php think clear → 清除runtime/cache/、runtime/log/、runtime/temp/全部内容。
【必须执行此步,否则调试模式残留会禁用所有缓存自动刷新逻辑】。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











