yii2缓存失效主因是过期、依赖变更或写入失败,非突然故障;常见问题包括纯数字键被拒存、dbdependency sql未返回标量、tagdependency漏删tag、多环境keyprefix缺失及目录权限不足。

Yii2.0 缓存失效不是“突然坏了”,而是有明确触发条件——要么过期时间到了,要么依赖项变了,要么缓存键/后端配置出问题。排查要顺着这几个环节一层层看,而不是直接清缓存重试。
查缓存是否真失效,还是压根没写进去
很多“失效”其实是缓存根本没成功写入。常见原因:
- 缓存键用了纯数字(如
time()、123),Yii2.0 的 FileCache/DbCache 会拒绝存储,set()返回true但实际没落盘,后续get()必然返回false - runtime/cache 目录权限不对,Web 进程无法写入文件
- Redis 连接失败或密码错误,但 Yii 默认不抛异常,
set()静默失败 - 用了
add()而非set(),但键已存在,新值不会覆盖
查过期时间与依赖是否触发失效
缓存没写错,但取出来是 false,大概率是被主动淘汰了:
- 检查
set($key, $value, $duration)中的$duration是否设得太短(单位是秒),比如误写成60(1分钟)而不是3600 - 若用了
DbDependency,它不是监听数据库,而是每次get()前重新执行 SQL——确认该 SQL 返回的是标量(一行一列),且结果确实会变(例如SELECT MAX(updated_at) FROM post,别写成SELECT 1) - 若用了
TagDependency,失效靠手动调deleteByTag(),不是自动联动;漏删某个 tag 就会导致缓存“假命中”
查多 APP 或多环境下的缓存隔离问题
跨应用读不到缓存,本质是路径或前缀冲突:
- FileCache 默认用各自
@app/runtime/cache,backend 和 frontend 的缓存物理隔离——想共享就得显式指定统一cachePath,比如都指向@common/runtime/cache - 多个应用共用 Redis 或 DB 缓存表时,必须配
keyPrefix,否则 A 应用存的user:123可能被 B 应用的同名 key 覆盖或误删 - 开发环境开了 debug 模式,某些缓存组件(如 FileCache)会自动禁用,只在生产环境生效
Yii3 和 Yii2 在缓存上的主要差异
Yii3 不是 Yii2 的简单升级,架构重构带来缓存机制的实质性变化:
- 缓存组件从
yii\caching\Cache拆为更细粒度的接口:比如yii\caching\CacheInterface+ 具体实现类,强制依赖注入,不再支持全局静态访问Yii::$app->cache - 默认缓存后端改为 PSR-6/PSR-16 兼容实现(如
symfony/cache),原生支持TagAwareAdapter,TagDependency的手动维护痛点被标准化解决 - 删除了 Yii2 中易混淆的
add()/set()区分,统一用set(),并引入setIfNotExists()替代add() - 查询缓存(
ActiveQuery::cache())在 Yii3 中被移除,官方推荐用服务层封装 + 显式缓存调用,避免 ORM 层过度耦合缓存逻辑 - HTTP 缓存过滤器
HttpCache保留,但 ETag / Last-Modified 的生成逻辑更倾向使用响应头中间件方式集成,而非控制器行为(Behavior)
不复杂但容易忽略:Yii2 的缓存失效,90% 是键命名、依赖 SQL 写法或目录权限的问题;Yii3 则把这些问题推到设计契约层面,用接口和标准约束代替灵活但易错的配置。











