Yii框架无内置定时清理缓存机制,需依赖被动检查、手动gc()或系统cron调用console命令;FileCache::gc()非自动任务,仅同步清理过期或全部文件;生产环境应使用cache/flush-all等命令配合cron定时执行。

Yii 框架本身不提供内置的「定时清理缓存」机制,所有缓存过期和清理都依赖被动触发(如 get() 时检查、gc() 手动调用)或外部调度(如 cron)。想靠 Yii 自己每天凌晨清一次缓存?不行——得自己搭。
FileCache 的 gc() 不是定时任务,只是手动触发的垃圾回收
FileCache::gc() 是一个同步方法,作用是遍历 cachePath 目录,删掉过期文件(或全部删掉)。它不会自动运行,也不会注册到系统定时器里。
- 默认情况下,
gc()只在缓存写入时「概率性触发」(由gcProbability控制,默认 100,即每次写都有机会执行) - 传
true给第一个参数($force),就能强制执行;传false给第二个参数($expiredOnly),就能清空整个目录 - 常见误用:
$cache->gc(true)—— 这其实等价于$cache->gc(true, true),只删过期项,不是「清空」
正确清空指定路径缓存的写法:
$cache = new \yii\caching\FileCache(); $cache->cachePath = '@frontend/runtime/cache'; $cache->gc(true, false); // 强制 + 清全部
想真正定时清理,必须靠系统 cron + Yii 命令行
Yii 提供了 cache/flush-all 和 cache/flush 控制台命令,它们能跨组件清理,且支持指定缓存组件名。这才是生产环境该用的方式。
- 先确认你的缓存组件在
console/config/main.php里已正确定义(和frontend/backend配置一致,尤其是cachePath) - 运行命令前,确保
./yii可执行,且当前用户有对应 runtime 目录的读写权限 - 示例:每天凌晨 2 点清空 frontend 缓存
0 2 * * * cd /var/www/myapp && ./yii cache/flush --interactive=0 --components=cache
注意:--components=cache 要和配置中缓存组件的 ID 一致(比如你配的是 'myFileCache',就得写 --components=myFileCache)
缓存过期不是「到点自动删」,而是「取的时候才检查」
Yii 的文件缓存不维护后台守护进程,过期时间(TTL)只在调用 get() 时通过比对文件修改时间和序列化中的过期时间戳来判断。这意味着:
- 过期文件可能长期留在磁盘上,直到下次
get()或gc()扫描到 -
set($key, $value, 3600)中的3600是逻辑过期,不是物理删除倒计时 - 如果某个缓存项永远没人读,它就永远不会被判定为过期,也不会被
gc()清掉(除非你传$expiredOnly=false)
所以「自动刷新」实际只能靠依赖(Dependency)驱动:比如用 DbDependency 监控数据表更新时间,一改就让缓存失效——但这不是定时,是事件驱动。
多应用共享缓存时,flush() 失效的根源和绕过方式
Yii::$app->cache->flush() 只清当前应用实例绑定的缓存组件所指向的路径。后台(backend)调用它,不会影响前台(frontend)的缓存目录——因为两者 cachePath 不同,且 $app 实例隔离。
- 错误思路:把所有应用缓存路径统一设成
@common/runtime/cache—— 会引发并发写冲突和权限问题 - 正确做法:在后台控制器里,显式构造目标缓存实例并调用
gc() - 关键点:路径必须写对,且用
Yii::getAlias()解析别名(@frontend在 backend 应用里默认不可解析,得手动补全)
后台清理 frontend 缓存的可靠写法:
$frontendCache = new \yii\caching\FileCache(); $frontendCache->cachePath = dirname(__DIR__, 2) . '/frontend/runtime/cache'; // 手动算路径 $frontendCache->gc(true, false);
这个路径计算方式比硬写 ../../frontend/runtime/cache 更健壮,也避免了别名未加载导致的解析失败。
缓存清理最易被忽略的一点:没有统一的缓存前缀或命名空间,TagDependency 和 gc() 就无法精准控制范围;而多个应用共用一套缓存逻辑时,cachePath 的绝对路径和权限必须提前对齐,否则 cron 脚本跑起来就是静默失败。











