生产环境关缓存须按类型逐层操作:模板编译需设view.cache_on=false并清runtime/view;路由缓存必须用php think route:clear;标签缓存需Redis游标扫描清理;数据缓存应设极短TTL或跳过缓存直查数据库;路由与标签缓存清理须原子执行。

生产环境不能靠 APP_DEBUG => true 关缓存,那只是开发兜底手段;真要关,得按缓存类型逐层关闭——模板编译、路由、数据缓存、标签索引,每类逻辑独立,关错一个就导致页面不更新或 404。
关模板编译缓存:别只改 config.php,还得确认 view 配置生效
TP6 模板缓存开关在 config/view.php 里,不是 config.php。常见错误是只在 config.php 加了 'TMPL_CACHE_ON' => false,但 TP6 已弃用该配置项,实际以 view.cache_on 为准。
-
view.cache_on设为false后,runtime/view/目录将不再生成任何 .php 编译文件 - 若已存在旧编译文件,需手动删掉
runtime/view/全部内容(保留空目录),否则仍会加载旧缓存 - 注意:关闭后每次请求都重新解析模板,CPU 开销上升,仅建议灰度验证期短期使用
清路由缓存:不能依赖 php think clear,必须单独执行
php think clear 默认不碰 runtime/route.php,这是线上路由 404 的最常见原因。哪怕你刚改完 route/app.php,没清路由缓存,新路由就永远不生效。
- 执行
php think route:clear是唯一可靠方式,它会重建runtime/route.php并重载全部路由定义 - 不要手动删
runtime/route.php后“等它自动生成”——TP6 路由缓存是启动时加载的,删了不触发重建,首次访问才会生成,期间全是 404 - 部署脚本中应把这步写死:
php think route:clear && php think clear -t,顺序不能反
标签缓存精准清除:动态标签名无法通配,得靠 Redis 游标扫描
Cache::tag('user_123')->clear() 只清单个标签,但生产环境常需清“所有 user_* 标签”。ThinkPHP 原生不支持模糊匹配,硬调 Cache::tag('user_*')->clear() 会静默失败。
立即学习“PHP免费学习笔记(深入)”;
- 必须直连 Redis,用
scan游标遍历:$keys = $redis->scan(0, 'tp_tag:user:*', 1000),避免keys命令阻塞线上服务 - 每个匹配到的
tp_tag:user:123是个 Set,需先sMembers拿出所有真实缓存 key,再逐个del - 切记最后
del掉标签索引本身,否则下次同标签写入会叠加旧 key - 标签名含变量时(如
'user_'.$uid),清理脚本必须和写入逻辑保持完全一致的拼接规则,否则漏清
关数据缓存:关驱动不如关 store,且 Redis 和 File 行为不同
想让 Cache::get() 完全绕过缓存,不是删配置,而是让 store 返回 null 或直通底层。直接设 'default' => null 会报错,正确做法是切换 store 行为。
- 文件缓存:设
'store' => 'file'后,在cache.stores.file.expire设为0,表示永不过期 → 实际等于不缓存(因每次 set 都覆盖) - Redis 缓存:不能设 expire=0(Redis 不认),得用
Cache::store('redis')->set($key, $val, 1)强制设 1 秒过期,靠极短 TTL 规避命中 - 真正停用某 store:在代码中判断环境,生产环境直接跳过
Cache::get(),走数据库查询,比“关缓存”更可控
最易被忽略的是标签缓存和路由缓存的耦合性——你清了 Redis 里的 tag 数据,但没清 runtime/route.php,新路由带缓存逻辑的控制器方法仍可能读到旧 tag 数据;反过来,路由清了但标签索引残留,下次写入会污染历史 key。两者必须视为原子操作。



















