必须将APP_ENV=prod且APP_DEBUG=false设为硬性前提,否则所有缓存层(Redis适配器、HTTP头、Doctrine查询缓存等)均被绕过而退化为filesystem;环境未生效是cache.app fallback的最常见原因。

缓存组件在 Symfony 7 中默认不生效,除非你确认 APP_ENV=prod 且 APP_DEBUG=false —— 这不是建议,是硬性开关。其他所有配置(Redis、TTL、标签)全在它之后才起作用。
为什么 cache.app 池始终 fallback 到 filesystem
最常见原因是环境没真正切到生产模式。Symfony 缓存组件会检测 APP_DEBUG 状态,只要为 true,所有池(包括 cache.app)都会强制退化为 cache.adapter.filesystem,哪怕你在 cache.yaml 里写了 Redis 配置也无效。
- 执行
php bin/console debug:container --env=prod | grep debug,输出中必须不含debug: true - 检查
.env和.env.local:确保APP_ENV=prod和APP_DEBUG=false同时存在,且.env.local没有覆盖前者 - 部署后必须运行
php bin/console cache:clear --env=prod && php bin/console cache:warmup --env=prod,否则var/cache/prod/下没有编译好的缓存类,容器会降级回运行时解析
用 Redis 替换默认缓存适配器的两个关键点
Symfony 7 推荐使用 cache.adapter.redis_tag_aware 而非基础 cache.adapter.redis,尤其当你需要按业务维度批量失效(比如“清空所有用户相关缓存”)时。但前提是 Redis 必须支持 SCAN 命令且版本 ≥ 6.2。
- 配置示例(
config/packages/cache.yaml):framework: cache: default_redis_provider: 'redis://127.0.0.1:6379' pools: cache.app: adapter: cache.adapter.redis_tag_aware provider: cache.default_redis_provider - 验证 Redis 可用:
redis-cli -h 127.0.0.1 ping必须返回PONG;若报错,检查防火墙、bind配置或 SELinux - 不要复用 Doctrine 的 Redis 连接池——
cache.adapter.redis_tag_aware需要独立连接,否则并发下可能触发连接竞争
HTTP 缓存头设置不对,HttpCache 就完全不工作
HttpCache 不解析 PHP 逻辑,只认响应头。设错一个字段,整条缓存链就断了。最常踩的坑是混淆 setMaxAge() 和 setSharedMaxAge()。
-
setMaxAge(3600)→ 输出Cache-Control: private, max-age=3600→HttpCache忽略(不缓存) -
setSharedMaxAge(3600)→ 输出Cache-Control: public, s-maxage=3600→HttpCache接收并缓存 -
setPublic()单独调用无意义,必须配合s-maxage或max-age才生成public标识 - 避免手动
setHeader('Cache-Control', ...):容易拼错语法(如漏空格、多逗号),优先用 Response 对象方法
Doctrine 查询结果缓存要配两处才生效
仅改 doctrine.yaml 不够。ORM 层缓存需同时启用“查询缓存”和“结果缓存”,且两者驱动必须一致(都指向 cache.app)。
- 在
config/packages/doctrine.yaml中:doctrine: orm: query_cache_driver: type: pool pool: cache.app result_cache_driver: type: pool pool: cache.app - 代码中必须显式调用:
$query->useResultCache(true, 3600, 'my_cache_key');不加这句,即使配置了也无效果 - 注意:实体关联映射(
OneToMany等)默认不参与结果缓存,需手动在@ORM\Cache注解中指定策略
缓存层级越深,依赖越严格:环境变量是地基,Redis 连接是管道,HTTP 头是协议,Doctrine 配置是附加层。漏掉任意一环,你以为在缓存,其实一直在走直通路径。



















