Horizon启动后Redis内存暴涨,需调优config/horizon.php:缩减trim值、禁用requests/redis指标、限制dashboard limit至20~50、关闭自动刷新,并停用Supervisor中的queue:work进程以避免冲突。

这里有个常见的误解需要先澄清:Horizon并非一个装上就能“自动变快”的监控工具。恰恰相反,它本身会消耗Redis资源、拖慢队列吞吐,如果配置不当,这个监控工具反而会成为新的性能瓶颈。
Horizon 启动后 Redis 内存暴涨怎么办
问题根源在于,Horizon默认会以极高的频率从Redis读取数据。每秒大量的 zrange、hgetall 和 llen 操作,在高并发场景下尤其致命。更麻烦的是,即便配置了前缀,它仍可能频繁触发类似 KEYS 的扫描行为,直接导致Redis CPU占用飙升和响应延迟拉高。
怎么解决?核心思路是“做减法”,关闭一切非必要的监控维度:
- 首要调整
config/horizon.php中的trim配置。将默认的'trim' => ['recent' => 100, 'failed' => 1000]改为更保守的值,比如50和200,这能显著减少历史数据占用的内存。 - 禁用实时图表中开销巨大的数据维度。在
'metrics' => ['jobs' => true, 'requests' => false, 'redis' => false]配置中,务必将requests和redis设为false,它们是资源消耗的大头。 - 最后,务必确认
.env文件中已正确设置HORIZON_PREFIX(例如HORIZON_PREFIX=horizon:)。如果这个前缀缺失,Horizon在扫描时会波及Redis全库的key,在生产环境这无异于一场性能灾难。
任务列表卡顿、加载超时的直接原因
打开Horizon的Web界面,发现任务列表加载缓慢甚至超时?这通常不是网络问题。界面默认会按时间倒序拉取全部的 recent_jobs,一旦单日任务量超过5万,前端请求 /horizon/api/jobs/recent 就很可能卡住10秒以上,最终触发Nginx 504网关超时。
优化方向很明确:限制数据量,变自动为手动。
- 放弃“全量加载”的幻想。在
config/horizon.php的'dashboard' => ['limit' => 50]配置里,果断将默认的100下调到20~50这个区间。 - 关掉前端的“Auto-refresh”自动刷新开关,改为需要时手动点击“Refresh”。这个小小的改动,能避免后台持续不断的轮询请求。
- 在失败任务页面,慎用“Retry All”按钮。批量重试会瞬间向Redis灌入大量新任务,极易压垮连接池。更稳妥的做法是使用
php artisan queue:retry [id]命令进行单条处理。
Supervisor 配置和 Horizon 进程冲突
这是一个典型的配置陷阱:同时使用Supervisor拉起 php artisan queue:work 和 php artisan horizon 进程。结果就是,两者会同时消费同一个Redis队列,导致任务被重复执行或状态记录错乱,场面一度十分混乱。
正确的部署姿势应该是“一山不容二虎”:
- 启动Horizon之后,必须确保停掉所有传统的
queue:work类进程。可以先运行php artisan horizon:terminate进行清理,再用ps aux | grep horizon检查,确保只剩下一个Horizon主进程。 - 在Supervisor的配置文件中,只保留Horizon的配置段。删除旧的
queue-worker段落,新增一个专门运行php artisan horizon的段落,并设置autostart=true即可。 - 记住,Horizon自带进程管理能力,不需要在Supervisor中配置
numprocs。各个队列的进程数量,应该在Horizon配置文件environments块内的processes参数中定义和调整。
说到底,Horizon的核心价值不在于“看得多”,而在于“看得准”。将 trim、metrics、limit 这几个关键配置项压缩到最低可用水平,再结合 failed_jobs 数据库表和Telescope工具来补充异常上下文,这才是一套稳定、可运维的监控组合拳。别让一个本该解决问题的工具,反而成了Redis的第一个“背锅侠”。
