Octane启动后缓存未生效,因worker进程仅首次fork时读取缓存,需执行php artisan octane:reload(Swoole)或php artisan octane:stop && php artisan octane:start(RoadRunner)强制刷新;部署时须先运行config:cache等预热命令,并确保view编译路径可读、Redis prefix配置静态且无重复拼接。

Octane 启动后缓存没生效?先确认是否跳过了预热阶段
Octane 默认以「按需加载」方式启动,config:cache、route:cache、view:cache 这些命令生成的缓存文件虽然存在,但 Octane 的 Swoole 或 RoadRunner 进程并不会自动 reload 它们——它只在首次 fork worker 时读取一次。如果你部署后直接访问首页发现配置没更新、路由 404 或 Blade 报错,大概率是 worker 进程还拿着旧内存快照。
解决办法不是重启整个 Octane,而是强制刷新 worker:用 php artisan octane:reload(Swoole)或 php artisan octane:stop && php artisan octane:start(RoadRunner)。注意:octane:reload 不会中断请求,但仅对新进请求生效;已有长连接可能仍走旧逻辑。
- 执行前确保已运行过
php artisan config:cache等预热命令,否则 reload 只是刷新空缓存 - CI/CD 部署脚本里,应在
octane:start前加一步php artisan view:clear && php artisan view:cache,避免残留编译文件干扰 - 若使用 Redis 作缓存驱动,Octane 默认复用连接池,但
Cache::put()写入的数据不会被其他进程“立刻看到”,因为 Laravel 的缓存门面在 Octane 下默认是进程隔离的(除非显式配置共享存储)
预热数据库查询结果时,别在 boot() 里直接查库
很多人把预热逻辑塞进 AppServiceProvider::boot(),想着“应用一启就跑”。但在 Octane 下,boot() 每个 worker 启动时都会执行一遍,如果里面包含 Category::all() 这类查询,等于每个 worker 都连一次 DB、查一次全表——10 个 worker 就发 10 次相同 SQL,白耗连接和 CPU。
正确做法是让预热只发生一次,且由主进程触发。推荐两种方式:
- 写一个独立 Artisan 命令(如
cache:warmup),在部署脚本末尾调用它,并确保该命令内部用Cache::store('redis')->put()显式指定驱动,绕过门面的进程上下文 - 利用 Octane 提供的
octane.starting事件,在EventServiceProvider中监听,加锁判断是否首个 worker:if (Cache::store('redis')->add('warmup_lock', true, 60)) { // 执行预热 } - 预热数据键名必须带业务前缀,比如
home:menu而非menu,否则容易和 Tinker 或队列进程写的缓存冲突
php artisan octane:status 显示 idle workers 却响应慢?检查视图预编译路径
Octane 的 worker 处于 idle 状态不代表它就 ready。常见现象是:状态显示 8/8 workers idle,但首屏加载仍要 1.2s,Debugbar 显示 view.compiled 耗时 800ms——说明 Blade 编译缓存没被 worker 正确加载。
根本原因是 Octane 默认从 storage/framework/views/ 读取编译文件,但这个目录权限或挂载方式可能让 worker 读不到(尤其 Docker 环境)。验证方法:进任意 worker 进程执行 php artisan tinker,然后输入 file_exists(storage_path('framework/views/xxx.php'))(随便找一个哈希文件名)。
- 若返回
false,说明路径不可见,需在docker-compose.yml中显式挂载该目录,或改用php artisan view:cache --force强制重写 - Blade 缓存文件权限应为
644,不能是600(worker 用户无法读取) - 不建议把
storage/framework/views放进.gitignore后又靠 CI 构建时生成——Octane worker 启动时需要的是文件存在,而不是构建动作
Redis 缓存预热后命中率低?检查 Octane 的连接复用配置
用 php artisan cache:warmup 往 Redis 写了数据,但线上监控显示 Cache Misses 高居不下,大概率是 Octane 的 Redis 连接没复用成功,导致每个 worker 自己建连接、自己维护本地缓存副本(Laravel 默认开启 cache.redis.options.prefix,但 Octane 下这个 prefix 可能被重复拼接)。
关键检查点:
- 确认
config/cache.php中 Redis 驱动的'prefix'是静态字符串,不要含env()或运行时计算(Octane 启动时只读一次配置) - 禁用
cache.redis.options.read_write_timeout或设为null,否则某些版本 Octane 在高并发下会因超时新建连接 - 用
redis-cli monitor观察实际写入键名,如果看到laravel_database_cache:home:menu和laravel_database_cache:laravel_database_cache:home:menu同时存在,就是 prefix 被叠用了
最稳妥的预热方式,是绕过 Laravel 缓存门面,直接用 Predis\Client 实例写入,确保键名和 TTL 完全可控——这对首页导航、站点配置这类强一致性要求的数据尤其重要。


















