Laravel Horizon处理mailcoach-feedback过慢(每分钟1任务)如何排查修复?
问题根因定位
你遇到的性能瓶颈核心是MySQL对JSON字段的无索引查询导致的,既不属于Mailcoach的设计缺陷,也不是核心配置错误:
- 你排查到的慢SQL对
webhook_calls表的payloadJSON字段直接用JSON_EXTRACT提取MessageId做过滤,没有对应索引的情况下,MySQL每次查询都要做全表扫描,逐行解析JSON内容,表数据量越大耗时越长,单核心CPU会被这类计算直接占满。 - 你将队列进程提升到10只会加剧问题:多个进程同时触发慢查询,CPU资源被占满后所有队列任务都会排队阻塞,处理速度自然无法提升。
修复方案
临时缓解措施
- 先将
mailcoach-feedback队列的进程数降回1~2,避免大量慢查询争抢CPU资源导致整体服务雪崩 - 清理
webhook_calls表中超过30天的历史无用数据,降低表总数据量可以临时降低查询耗时 - 给服务器添加1GB大小的Swap分区,缓解内存不足导致的MySQL性能下降
永久修复方案
- 给JSON字段的
MessageId添加生成列和索引
执行以下SQL即可,不需要修改Mailcoach的业务代码,MySQL查询优化器会自动将原JSON字段查询匹配到新索引上:
-- 添加存储类型的生成列,自动同步JSON中的MessageId值 ALTER TABLE `webhook_calls` ADD COLUMN `message_id` VARCHAR(255) GENERATED ALWAYS AS (JSON_UNQUOTE(JSON_EXTRACT(`payload`, '$.MessageId'))) STORED; -- 给生成列添加普通索引 CREATE INDEX `idx_webhook_calls_message_id` ON `webhook_calls`(`message_id`);
加完索引后原慢SQL的耗时会降到毫秒级,CPU占用会直接回落。
- 优化Horizon配置
- 单核心服务器的Horizon总进程数不要超过3个,进程过多会因为CPU上下文切换反而降低性能
- 将
mailcoach-feedback队列的timeout参数从600调整为60,避免异常卡住的进程长期占用资源 - 把队列进程的
memory参数调整为256,避免PHP进程因为内存不足被意外杀死
- 长期优化建议
- 定期清理
webhook_calls表的历史数据,建议保留不超过90天的webhook记录 - 开启MySQL慢查询日志,定期巡检未加索引的慢查询
- 如果后续邮件发送量持续提升,建议升级到2vCPU配置的服务器,PHP队列和MySQL都对CPU资源比较敏感。
内容的提问来源于stack exchange,提问作者Ryan
相关产品推荐
相关产品推荐

