yii2.0.47缓存失效依赖访问检查和显式触发,关键在避免静默降级(如redis配置错误导致fallback到dummycache)、规范缓存键设计(禁用纯数字key、加前缀、细粒度+tagdependency)、正确批量失效(复用tagdependency实例并统一环境调用invalidate)。

Yii2.0.47 的缓存失效不是靠后台定时扫描,而是依赖“访问时检查”和“显式触发”。想让缓存真正可控、不堆积、不误失,关键在三点:避免静默降级、控制键生命周期、用对失效方式。
别让 Redis 连不上还假装在工作
缓存组件 fallback 到 DummyCache 是最隐蔽的性能黑洞。你看到 get() 返回 false,日志里没 Redis 连接记录,基本就是配置没生效:
- 必须单独定义 redis 组件,不能只在 cache 配置里嵌套 'redis' => []
- cache 类名写成 'yii\redis\Cache',别拼错成 yii\caching\RedisCache(该类不存在)
- 开了密码或用了非默认 database(比如 database=2),但 redis 组件里漏了 'password' 或 'database' 配置
- 用 $cache->exists($key) 测试前,先确认 Yii::$app->redis->ping() 能通
缓存键设计决定命中率上限
命中率低,90% 不是 Redis 没起作用,而是 key 写得太“飘”:
- 纯数字 key(如 time()、$id)可能被某些驱动截断或序列化异常,建议统一加前缀,如 'user_'.$id
- 避免动态拼接无标准化的 key,'order_123_v1' 和 'order_123_v2' 是两个独立 key,旧数据过期后新请求全 miss
- 不要缓存整张表(如 'all_products'),改用带标签的细粒度缓存 + TagDependency
- 开发/测试/生产共用 Redis 实例时,务必设 keyPrefix,否则互相覆盖
批量失效别靠删 key,要用 TagDependency
Yii2 没原生 tag 支持,但 TagDependency 能模拟出可靠的批量失效能力:
- 所有关联缓存项必须复用同一个 TagDependency 实例,不能每次 new 一个
- tags 参数只接受字符串,如 'product_list',不能传 ['tag1','tag2'] 数组
- 清除时调用 TagDependency::invalidate(['product_list']),不是 $cache->delete()
- 确保 invalidate() 调用环境与 set() 时的缓存前缀、Redis database 完全一致,否则失效失败
过期不是自动清理,得有人推一把
文件缓存或 Redis 缓存都不会主动删过期项,得靠触发机制释放空间:
- FileCache 的 gc() 默认只在写入时按概率执行(gcProbability=100 即每次都有机会),生产环境建议关掉概率,改用 cron 调用 console 命令
- Redis 缓存本身支持 LRU/LFU 过期淘汰,但业务层仍需配合:set($key, $val, 3600 + mt_rand(0, 600)) 加随机偏移,防雪崩
- 高频无效请求(如 /user/9999999)要加布隆过滤器或空值缓存(带短 TTL,如 60 秒),否则直接穿透 DB 拉低命中率
- 监控真实命中率:定期查 redis-cli info stats,看 keyspace_hits / (keyspace_hits + keyspace_misses) 比值,别只看应用层统计











