ThinkPHP缓存失效需先验证是否真实发生:用dump(cache('key'))、Cache::has()/get()确认读值,开启cache日志并检查key哈希、runtime/cache权限、APP_DEBUG=false,Redis需直连验证及KEYS检查,标签清除须全小写且用set()配合tag()。

ThinkPHP缓存失效不是单一原因导致的,而是配置、环境、驱动、路径、权限多个环节叠加作用的结果。最常见的是“以为缓存没更新”,实际是根本没写进去,或读的是另一个key、另一份缓存、甚至另一个服务器进程。
先确认是不是真失效了
别急着删缓存或改代码,先验证现象是否真实存在:
- 在控制器里加
dump(cache('user:123', 'not_found'));,看输出是不是你预期的新值; - 用
Cache::has('user:123')和Cache::get('user:123')分开测试,避免误判 null 是“未命中”还是“存了 null”; - 开启缓存日志:在
config/cache.php中设置'logger' => 'cache',并在config/log.php配置对应通道,确保runtime/log/cache/可写且日志级别为debug; - 检查 key 是否被哈希——你传
'user:123',底层可能存成一长串哈希名,导致手动清理或直查失败。
文件缓存写不进 runtime/cache/
这是开发阶段最高频的问题,表面是“缓存不刷新”,实则是“压根没存上”:
- 检查
runtime/cache/目录权限,Web 进程用户(如 www-data)必须有读写权限; - 用
touch runtime/cache/test.php测试能否创建文件; - 若项目自定义了
RUNTIME_PATH,请先var_dump(RUNTIME_PATH)确认真实路径,避免清理了错误目录; - TP5/TP6 在 APP_DEBUG=true 下会跳过缓存写入逻辑,哪怕你调用了
cache(),也可能静默忽略——务必确认config('app.app_debug')输出为 false。
Redis 缓存看似连上了,其实没生效
配置写对 ≠ 缓存真在用 Redis。很多问题出在连接假成功:
立即学习“PHP免费学习笔记(深入)”;
- 执行
php -r "print_r((new Redis())->connect('127.0.0.1', 6379) && (new Redis())->auth('your_pass'));"直连验证; - 检查
config/cache.php中password、database是否匹配 redis.conf,TP 默认用 DB 0; - 用
redis-cli -a your_pass KEYS cache_*查是否有数据,没有就说明写入失败,不是命中问题; - Redis 驱动下
Cache::clear()默认执行FLUSHDB,若和其他服务共用一个 DB,会误清他人缓存——建议单独分配 DB 或改用 tag 清理。
标签(tag)清除不生效?名字和写法都得严丝合缝
ThinkPHP 的 tag 不是模糊分类,而是靠元数据文件映射,拼错一个字符就找不到:
- 标签名必须全小写、无空格、无冒号,比如
'user_list'可以,'UserList'或'user:list'就失败; - 设置带标签的缓存必须用
Cache::tag('user')->set('key', $data, 3600),不能用cache('key', $data, 3600, ['tag'=>'user'])(无效); - Apcu、Memcached 驱动不支持 tag,开了也白开;
- 清理时用
Cache::tag('user')->clear(),注意不要漏掉括号,也不要写成Cache::tag('user')->clear('key')(该方法不存在)。



















