yii 2.x 默认支持 filecache、apccache、memcache、rediscache 等缓存驱动,但需对应 php 扩展已安装并正确配置;filecache 无需扩展但高并发下易因文件锁导致性能下降,apccache 依赖 apcu 且需启用 apc.enable_cli,memcache 仅支持 memcache 扩展(非 memcached),rediscache 为生产环境推荐方案。

Yii 2.x 默认支持哪些缓存驱动
Yii 2 的 yii\caching\Cache 是抽象基类,真正起作用的是它的子类:比如 yii\caching\FileCache、yii\caching\ApcCache、yii\caching\MemCache、yii\caching\RedisCache 等。不是所有驱动都“开箱即用”,得看 PHP 扩展是否装好、配置是否对。
常见误区是以为只要配了 class => 'yii\caching\ApcCache' 就能跑——其实 PHP 必须已加载 apcu 扩展(注意:不是旧版 apc),且 apc.enable_cli 在 CLI 模式下也要开,否则命令行任务缓存会静默失效。
-
FileCache:无需扩展,但并发写多时可能因文件锁导致延迟;适合开发或低流量场景 -
ApcCache:依赖apcu,速度快、进程内共享,但不跨机器;PHP 7.4+ 默认启用,但需确认apc.enable_cli=1 -
MemCache:走网络,支持分布式,但单点故障风险高;注意它用的是memcache(非memcached)扩展,函数名是memcache_connect(),别装错扩展 -
RedisCache:推荐生产环境首选;要求phpredis扩展,连接池、持久化、过期策略都更可控
FileCache 在高并发下为什么缓存命中率突然掉?
根本原因不是 Yii 实现问题,而是底层文件系统行为:FileCache 把每个缓存项写成独立小文件,目录结构按 key 哈希分层(如 abc/def/xyz.cache)。当并发写入量大时,大量进程同时 open/write/flock 同一目录下的文件,会触发 ext4/xfs 的目录锁争用,I/O 等待飙升。
- 现象:日志里没报错,但
get()返回null、set()耗时从几 ms 涨到 200+ ms - 临时缓解:调大
cachePath下的子目录层级(如从 2 层改到 3 层),分散文件压力 - 长期方案:别在生产用
FileCache;若必须用,至少挂 SSD,且确保opcache.file_cache关闭(避免和 opcache 文件缓存打架)
MemCache 和 Memcached 扩展在 Yii 里怎么选?
Yii 官方只原生支持 memcache 扩展(对应类 yii\caching\MemCache),不支持 memcached(带 d)扩展。后者功能更强(SASL、二进制协议、更好的压缩),但 Yii 没封装它——硬要用就得自己写 Cache 子类,或者换 RedisCache。
- 错误配置示例:
'class' => 'yii\caching\MemCache', 'servers' => [['host' => '127.0.0.1', 'port' => 11211]]→ 如果 PHP 没装memcache扩展,启动直接报Class 'Memcache' not found - 检查方法:运行
php -m | grep memcache,看到memcache(无 d)才对 - 兼容性注意:
MemCache不支持addServer()的权重参数,多实例只能靠数组轮询,没法做主备
APC 缓存失效后为什么查不到数据,连调试日志都不打?
因为 ApcCache::get() 在遇到 APCU 不可用时,会直接返回 false,而 Yii 的 Cache::get() 默认把 false 当作“缓存未命中”,继续往下走业务逻辑——整个过程没有 warning,也没有抛异常,非常安静。
- 典型诱因:PHP 升级后
apcu没重装;或 CLI 模式下apc.enable_cli=0(Web 服务正常,但 cron 任务全走数据库) - 验证方式:在代码里加一行
var_dump(extension_loaded('apcu'));,再查phpinfo()里 APCU 是否 enabled - 安全做法:上线前加个健康检查,比如在
bootstrap.php里强制调一次$cache->set('test', 1); $cache->get('test'),失败就 throw Exception
APC 和 Memcache 这类进程级或外部缓存,最容易被忽略的是“冷启动”问题:刚重启 PHP-FPM 或 Memcached 服务时,缓存全空,流量高峰直接打穿 DB。得配合预热脚本或降级策略,不能只靠配置文件里写个 class 名就完事。











