同一服务器上两个Laravel Horizon实例任务冲突问题求助
问题
我有一台测试服务器,运行着两个完全相同的Laravel应用版本,各自配有独立的Laravel Horizon实例(一个是新功能预发布站点stg,一个是镜像生产环境的演示站点demo)。这些应用部署在Docker容器中,共享同一个Redis数据库(即单个Redis容器,两个独立PHP容器运行Horizon)。它们已稳定运行数月,但近一周出现异常。
最初发现问题时,我意识到未为每个站点设置HORIZON_PREFIX环境变量,随后已分别配置为stg:和demo:以区分。我执行了Redis的FLUSHDB命令,并重启所有Docker容器,重启时会运行脚本重置应用缓存:
echo 'Clearing previous cache...' (cd /var/www/html && php artisan cache:clear && php artisan config:clear && php artisan route:clear && php artisan view:clear) echo "Caching configuration..." (cd /var/www/html && php artisan config:cache && php artisan route:cache && php artisan view:cache) echo "Starting Laravel application..."
但设置独立前缀后,提交任务时仍会同时发送到stg和demo队列。查看Redis数据库,已实现stg和demo的键分离,但问题依旧:提交到demo的任务会被两个Horizon实例接收,在stg上执行失败,在demo上则卡在待处理任务列表;关闭stg站点后,任务可在5秒内成功完成。
Redis键列表如下:
127.0.0.1:6379> KEYS * 1) "demo:monitor:time-to-clear" 2) "demo:measured_jobs" 3) "stg:supervisor:7e9026e6c9b7-6nE4:supervisor-2" 4) "demo:db636ed0-c5ac-4233-9867-aed91e9397af" 5) "demo:masters" 6) "stg:last_snapshot_at" 7) "stg:monitor:time-to-clear" 8) "demo:master:3a70f005424b-Bteh" 9) "stg:supervisor:7e9026e6c9b7-6nE4:supervisor-0" 10) "stg:failed:App\Models\CustomList:79" 11) "demo:queue:default" 12) "stg:masters" 13) "demo:last_snapshot_at" 14) "demo:9fcc3255-cb91-4ad6-ada1-24528c806b63" 15) "demo:pending_jobs" 16) "stg:failed_jobs" 17) "stg:failed:App\Models\CustomList:48" 18) "stg:recent_failed_jobs" 19) "stg:9fcc3255-cb91-4ad6-ada1-24528c806b63" 20) "demo:supervisor:3a70f005424b-Bteh:supervisor-0" 21) "stg:supervisor:7e9026e6c9b7-6nE4:supervisor-1" 22) "demo:measured_queues" 23) "stg:master:7e9026e6c9b7-6nE4" 24) "stg:db636ed0-c5ac-4233-9867-aed91e9397af" 25) "stg:6d53039b-dcd9-41f6-af5e-3c89203dd6e7" 26) "demo:completed_jobs" 27) "demo:supervisors" 28) "demo:supervisor:3a70f005424b-Bteh:supervisor-2" 29) "stg:supervisors" 30) "demo:d96f69ba-60fd-4d2f-a8c0-1a8091cb98bf" 31) "demo:job:App\Jobs\SyncData" 32) "demo:supervisor:3a70f005424b-Bteh:supervisor-1" 33) "demo:0705c7ec-d81e-4e26-9f40-d5c045e33c5b" 34) "stg:b159e41e-fb2e-40f9-9c3e-c404deb1bacd" 35) "demo:6d53039b-dcd9-41f6-af5e-3c89203dd6e7" 36) "demo:recent_jobs" 37) "demo:b159e41e-fb2e-40f9-9c3e-c404deb1bacd" 127.0.0.1:6379>
版本信息:
Laravel Horizon v5.16.1 Laravel v9.52.9
请问还需执行哪些操作才能避免这种任务冲突?
解决方案
- 确认Horizon配置文件的前缀读取逻辑:检查
config/horizon.php中的prefix配置项,确保是'prefix' => env('HORIZON_PREFIX', 'horizon:'),,而非硬编码的固定值,保证环境变量能被正确读取。 - 强制Horizon进程优雅重启:进入每个PHP容器内部,执行
php artisan horizon:terminate,让Horizon完全重启加载新配置。仅重启Docker容器可能无法让Horizon进程重新读取配置。 - 验证队列连接的前缀一致性:查看
config/queue.php中Redis连接的prefix配置,确保和对应站点的HORIZON_PREFIX保持一致,避免任务投递时使用了错误的前缀。 - 重新发布Horizon配置(若有自定义修改):执行
php artisan horizon:publish,覆盖旧的配置文件,确保最新的前缀规则被应用,之后重新执行配置缓存命令。 - 检查Redis全局前缀:确认Redis服务的
redis.conf中未设置全局prefix,避免全局前缀和Horizon的前缀叠加导致队列识别混乱。 - 清理Horizon监控数据:执行
php artisan horizon:clear清除Horizon的快照、监控数据,避免旧的跨站点数据残留干扰任务调度。 - 验证任务投递目标队列:提交测试任务后,用Redis命令确认任务仅进入对应前缀的队列(比如demo任务只在
demo:queue:default中),排查是否存在任务投递逻辑错误。
内容的提问来源于stack exchange,提问作者Nathan
相关产品推荐
相关产品推荐

