horizon启动后redis cpu和内存暴涨,因其默认每秒执行zrange、hgetall、llen等高开销命令,未设horizon_prefix时更会触发keys*全库扫描,导致redis过载。

Horizon 不是高并发的“自动解药”,它本身会成为 Redis 的压力源;必须手动压低采集粒度、隔离队列资源、禁用冗余轮询,否则吞吐量反而下降。
为什么 Horizon 启动后 Redis CPU 和内存暴涨
Horizon 默认每秒执行大量 ZRANGE、HGETALL、LLEN 命令,尤其在未设 HORIZON_PREFIX 时会触发 KEYS * 扫描——这在生产 Redis 上等于拒绝服务。高频任务场景下,它比业务队列本身更消耗连接和 CPU。
- 必须在
.env中显式设置HORIZON_PREFIX=horizon:,否则所有 key 匹配失效 - 关闭非必要指标:把
config/horizon.php中的'metrics' => ['jobs' => true, 'requests' => false, 'redis' => false],requests和redis是最重的两项开销 -
'trim' => ['recent' => 50, 'failed' => 200, 'completed' => 200],默认 1000 会堆积大量元数据,但注意:这个值只控制 UI 展示上限,不清理底层数据 - 真正释放内存靠
php artisan horizon:clear,不是horizon:terminate(后者只杀进程)
如何让 high 队列不被 default 拖慢
Horizon 不支持 priority 参数,所谓“权重”本质是进程数分配 + 队列隔离。auto 平衡模式在突发流量下响应滞后,容易导致高优任务积压。
- 在
config/horizon.php的environments下为不同队列写死进程数,例如:'high' => ['processes' => 6]、'default' => ['processes' => 2] - 把
'balance' => false,禁用自动均衡,防止 Horizon 覆盖你的手动配置 - 确保各队列使用独立 Redis 连接(如
redis-high和redis-default),避免共享连接池阻塞 - 验证是否生效:用
redis-cli llen queues:high和llen queues:default对比 pending 数,再看ps aux | grep horizon是否真起了对应数量的子进程
Web 界面卡顿、加载超时怎么办
前端请求 /horizon/api/jobs/recent 默认拉取全量 recent_jobs,单日任务超 5 万时,Redis 响应常超 10 秒,Nginx 直接返回 504。
- 把
config/horizon.php中'dashboard' => ['limit' => 50]改成20,这是最直接有效的缓解 - 关掉右上角 “Auto-refresh”,改手动点 Refresh;持续轮询会维持大量空闲连接,压垮 Redis
- 不要点 “Retry All” —— 它会瞬间向 Redis 写入数千新 job,可能触发连接池耗尽或
OOM command not allowed错误 - 失败任务分析建议导出 ID 列表,用
php artisan queue:retry [id]单条重试,可控且可审计
Supervisor 配置与 Horizon 进程冲突的硬伤
同时运行 queue:work 和 horizon 是最常见错误:两者都消费同一 Redis 队列,造成任务重复执行、状态错乱、failed_jobs 表污染。
- Horizon 启动前,必须运行
php artisan horizon:terminate清理残留,并确认ps aux | grep queue:work无任何输出 - Supervisor 配置里只保留一个 program 段:
command=php artisan horizon,删掉所有queue:work相关段 -
numprocs不要设 —— Horizon 自带进程管理,它的environments配置块已定义每个队列的processes,改那里就行 - 启动后检查
ps aux | grep horizon:应只有 1 个主进程 + N 个 worker 子进程;若只有主进程,说明supervisorctl update没生效或配置语法错误
最易被忽略的一点:Horizon 的价值不在“看得全”,而在“看得准”。trim、metrics、limit 三个配置项压到最低可用值后,配合 failed_jobs 表 + Laravel Telescope 补上下文,才是稳定线上的真实路径。











