定时清理必须用系统级任务,ThinkPHP无内置调度器,cache.php的expire仅控制单条缓存存活时长,不触发物理删除;Linux用crontab、Windows用任务计划程序,且crontab须用绝对路径并cd进项目目录执行php think clear:cache。

定时清理必须用系统级任务,框架不自带调度器
ThinkPHP 没有内置定时任务调度器,cache.php 里的 expire 只控制单条缓存存活时长,不会触发物理删除。所谓“自动清理”,全靠你配外部定时器。
Linux 下用 crontab 是最稳的选择,Windows 则用任务计划程序。别指望在 config/cache.php 里加个参数就让缓存自己扫地——它连扫帚都没有。
- crontab 必须用绝对路径:
/var/www/myapp,不能写~/myapp或./myapp - 命令前要
cd进项目目录,否则php think clear:cache找不到入口文件 - 避免用
php think clear --all,它会清runtime/log/,线上日志丢了没法回溯问题
file 驱动下过期文件不删,得手动筛时间删
File 缓存驱动只在 Cache::get() 时检查 expire,从不主动删磁盘文件。runtime/cache/ 目录几天就能涨到几万个小文件,du -sh runtime/cache 一看吓一跳。
直接 php think clear:cache 是全量清空,不适合日常维护;更安全的做法是按修改时间删旧文件:
立即学习“PHP免费学习笔记(深入)”;
- 保留最近 24 小时的缓存:
find runtime/cache -name "*.php" -mmin +1440 -delete - 跳过当天日志类缓存(如带日期命名的目录):加
-type f限定只删文件,不碰目录 - PHP 自定义命令里要用
filemtime()判断,别用date('Y-m-d')字符串匹配,防文件名被篡改
redis 驱动依赖自身机制,但别信“即时清理”
Redis 的 EXPIRE 是惰性+定期混合清理,高并发时大量 key 过期后仍堆积在内存里,INFO memory 里 expired_keys 持续上涨就是信号。
Cache::clear() 在 Redis 驱动下默认执行 FLUSHDB,不是按前缀删,容易误伤其他业务数据:
- 确认
config/cache.php中redis配置启用了prefix,比如'prefix' => 'think_cache:' - TP6.3+ 支持
Cache::clear('', 'redis', ['prefix' => 'think_cache:']),但该参数未进文档,得看源码确认是否可用 - 真要精准删,绕过门面直连 Redis:
Cache::store('redis')->handler()->keys('think_cache:*'),再逐个del(注意KEYS命令生产环境慎用)
别在 Web 请求里调用清理逻辑,后果不可控
有人想在用户更新资料后立刻清缓存,于是在事件监听器里写 exec('php think clear:cache') —— 这行不通。Web 环境没有 shell 权限,exec 调用会失败,且极不安全。
可行方案只有两个:
- 监听器里用 PHP 原生函数删目录:
File::deleteDir(cache_path()),但仅限 file 驱动;Redis 还得另起 CLI 进程处理 - 把清理动作下沉到队列或定时任务:用户更新后发消息到 Redis 队列,由 worker 进程在 CLI 下跑
php think clear:cache或自定义命令
真正难的不是“怎么删”,而是删哪、什么时候删、删完会不会影响正在读缓存的请求——这些得结合你的缓存粒度、key 命名规则和驱动类型一起判断,不能套模板。



















