缓存预热应在业务低峰、部署后或大促前10–30分钟触发;需避开opcache/apcu清空后立即执行,确保Redis连通性,并预热高频读、低更新、高构建成本的热点数据,如商品详情、活动规则等。

缓存预热该在什么时候触发
预热不是启动时随便跑一遍就完事,它得卡在业务低峰、部署后、或大促前 10–30 分钟执行。PHP 没有常驻内存机制,所以不能靠 __construct 或全局初始化自动做;常见错误是把预热逻辑塞进前端入口(比如 index.php),结果每次 HTTP 请求都跑一次,反而拖垮响应。
- 推荐用 CLI 模式执行:运行
php artisan cache:warmup(Laravel)或自定义php warmup.php - 避免在
opcache_revalidate_path或apcu_clear_cache后立刻预热——APCu/Opcache 刚清空,数据还没写入,容易漏 - 如果用 Redis,确认
redis-cli -h xxx ping返回PONG再开始,否则预热脚本静默失败
怎么选要预热的数据
不是所有缓存都值得预热。热点数据 = 高频读 + 低更新频次 + 构建成本高。比如商品详情页的 SKU 基础信息、活动规则配置、地区三级联动数据。但用户 session、临时 token、带时间戳的验证码,预热了也白搭——过期快、个性化强。
- 从慢查询日志或 APM 工具(如 Blackfire、XHGui)里抓出
SELECT * FROM products WHERE id IN (...)这类高频 SQL,对应缓存 key 就是预热目标 - 用
cache:keys(Redis CLI)或apcu_cache_info()快速看当前有哪些 key,排除以user:、session:开头的 - 别硬编码 key 列表:从数据库查出 top 100 商品 ID,拼成
['product:1001', 'product:1002', ...]动态生成
PHP 实现预热的三种安全写法
直接 file_get_contents 或 cURL 访问接口触发缓存?危险。这等于把预热变成一次真实请求,可能触发埋点、风控、库存扣减等副作用。必须绕过路由和中间件,直连数据层。
- CLI 脚本中 new 一个
ProductService,调getDetail($id)方法,内部走Cache::remember—— 不走 HTTP 层 - 用 PDO 直连 MySQL 查数据,再
Redis::set($key, $data, ['EX' => 3600]),跳过 ORM 和缓存驱动封装 - 如果是 APCu,注意
apcu_store($key, $value, $ttl)的$ttl是秒数,且不支持毫秒;设成0表示永不过期,但服务器重启就丢
预热失败怎么快速定位
最常被忽略的是权限与上下文问题:CLI 用户(如 www-data)和 Web 用户(如 nginx)可能用不同 Redis DB、不同 APCu segment、甚至不同 php.ini 配置。
立即学习“PHP免费学习笔记(深入)”;
- 检查
php -i | grep apc和php -r "print_r(apcu_cache_info());"输出是否和 Web 环境一致 - Redis 预热后用
redis-cli KEYS "product:*" | wc -l数 key 数量,别只信返回值TRUE - 加一行
error_log("warmup product:1001 done", 3, '/tmp/warmup.log');,别依赖echo—— CLI 下 stdout 可能被重定向或丢弃
预热不是“跑完就放心”,而是每次部署后都要验证 key 是否真进了缓存、TTL 是否符合预期、有没有因序列化方式不同(比如 igbinary vs php_serialize)导致 Web 进程读不出来。这些细节不验,高峰期照样打回原形。











