最稳的PHP多级缓存组合是Redis作一级缓存、APCu作二级缓存:Redis存高频可共享数据,APCu存本机独享只读配置,兼顾性能与一致性。

Redis 作一级缓存、APCu 作二级缓存最常用
PHP 多级缓存不是堆得越多越好,而是要按访问频次、数据生命周期和一致性要求分层。生产环境最稳的组合是:Redis 存高频可共享的数据(如用户会话、热点商品),APCu 存本机独享的、只读且变化极慢的配置或模板元数据(如路由映射、语言包哈希)。这样既避免 Redis 网络开销拖慢本地高频读,又防止 APCu 进程隔离导致集群数据不一致。
常见错误是把所有东西都往 Redis 塞——结果 get_config() 每次都走 TCP,QPS 上不去;或者全用 APCu——多实例部署后缓存不同步,改个开关要等所有机器重启。
-
APCu只在单进程内有效,不能跨 PHP-FPM worker 共享,更不能跨服务器 -
Redis支持过期、原子操作、发布订阅,但引入网络延迟和连接池管理成本 - 若用
Memcached替代Redis,注意它不支持复杂数据结构,incr/decr行为也略有差异
文件缓存仅适合低并发调试场景
别被 file_get_contents() + serialize() 的简单迷惑。文件缓存在高并发下容易触发 inode 锁争用,flock() 不到位时还会出现脏读。CI/CD 流水线里临时用它存构建产物没问题,但线上 Web 请求中作为二级缓存,stat() 频繁调用会直接拉高系统负载。
如果你非要用文件缓存,请确保:
立即学习“PHP免费学习笔记(深入)”;
- 缓存目录挂载在
tmpfs(内存文件系统),避开磁盘 IO - 每个缓存项用独立文件,避免大文件锁整块区域
- 加前缀隔离命名空间,比如
/tmp/cache/v2/user_123.json,别用md5(serialize($data))当文件名——太难 debug
OPcache 不是缓存引擎,别把它当二级缓存用
OPcache 是 PHP 字节码缓存,只加速 .php 文件解析,对 json_decode() 结果、new stdClass() 对象、file_get_contents() 读出来的字符串完全无效。很多人误以为开启 opcache.enable=1 就“有缓存了”,结果数据库查询结果还在裸奔。
它的作用边界非常明确:
- 缓存编译后的 opcode,减少重复 parse 和 compile
- 不缓存运行时数据,也不参与任何应用层缓存逻辑
- 和
APCu可共存,但两者数据完全不互通——apcu_store('key', $val)不会影响OPcache的命中率
选型要看部署拓扑,不是看 benchmark 数值
单机 Docker 环境跑 Redis + APCu 没问题;但 Kubernetes 下如果每个 Pod 自带 Redis 实例,就变成资源浪费+状态分散。这时候该换成 Redis Cluster 或托管服务(如 AWS ElastiCache),而本机缓存仍用 APCu。
另一个常被忽略的点:PHP 版本兼容性。PHP 8.0+ 的 APCu 默认关闭 apc.enable_cli=1,命令行脚本里 apcu_fetch() 会静默失败;Redis 扩展在 PHP 7.4 和 8.2 中的 connect() 超时参数名也从 ['timeout' => 2] 变成 ['tcp://127.0.0.1:6379?timeout=2']。
缓存层级越深,失效路径越难追踪。与其堆三级缓存,不如先确认 Redis 是否用了连接池、APCu 是否开了 apc.shm_size 足够大、关键数据有没有加 version 前缀防雪崩——这些细节比引擎名字重要得多。











