Laravel队列需通过queue:work启动消费者进程,配置重点是Redis驱动、连接参数、QUEUE_CONNECTION环境变量及APP_KEY一致性;queue:listen已废弃,应使用queue:work配合supervisor管理。

直接说结论:Laravel 队列本身不“开启”,而是靠 php artisan queue:work 这类命令启动消费者进程;真正要配置的是驱动(如 Redis)、连接、队列名和失败处理机制。
Redis 驱动怎么配才不报 Connection refused
多数人卡在这步——不是 Laravel 配错了,是 Redis 服务没跑或配置对不上。
-
REDIS_HOST和REDIS_PORT必须和redis-cli -h xxx -p xxx ping能通的地址一致,别默认写127.0.0.1却在 Docker 里跑 Laravel 容器 -
QUEUE_CONNECTION=redis要写进.env,不是只改config/queue.php - 检查
config/queue.php中redis连接是否用了正确的connection名(默认是default),且该 connection 在config/database.php的redis配置里存在 - Redis 密码必须用
REDIS_PASSWORD设置,且不能带空格或特殊字符(否则parse_url解析失败)
queue:work 和 queue:listen 到底用哪个
queue:listen 已被废弃(Laravel 5.7+),别再用。所有现代项目只用 queue:work。
-
php artisan queue:work:常驻内存,启动快、开销低,但代码更新后需手动restart -
php artisan queue:work --daemon:旧版守护模式,已移除,现在--daemon是默认行为,不用加 - 要自动重载代码?用
supervisor管理进程 +--max-jobs=100或--max-time=3600防止内存泄漏 - 开发时加
--once手动触发单条任务,避免进程挂起干扰调试
任务推到队列却没执行?查这三处
常见假象:“写了 dispatch() 就以为队列动了”,其实可能根本没走 Redis,或者消费者压根没启动。
- 确认
QUEUE_CONNECTION是redis,不是sync(sync是同步执行,不走队列) - 运行
php artisan queue:work --verbose,看输出是否有Processing或Failed日志;没日志说明进程根本没收到任务 - 用
redis-cli直接查:LRANGE queues:default 0 -1(队列名取决于queue参数,默认default),有数据说明推成功了,没数据就回头检查 dispatch 是否被条件跳过或异常中断 - 任务类里
handle()抛出未捕获异常会导致任务失败并进入failed_jobs表(如果启用了database失败存储),别忽略php artisan queue:failed输出
Redis 队列积压怎么办
不是调大 retry_after 就能解决,得先分清是慢还是卡。
-
retry_after(在config/queue.php的redis配置里)设太短(如 3 秒),但任务实际要 10 秒,会导致重复消费;建议设为任务最长耗时的 2 倍 - 用
redis-cli查llen queues:default看长度,再用lrange queues:default 0 4抽样看任务结构,确认是不是序列化失败(比如闭包、资源句柄被塞进队列) - 高并发下多个
queue:work进程争抢同一队列,可按业务拆分:用dispatchOn('emails')推到emails队列,再单独起php artisan queue:work --queue=emails进程 - Redis 内存满或
maxmemory-policy设成noeviction会导致LPUSH失败,此时 Laravel 不报错但任务丢失——务必检查 RedisINFO memory和CONFIG GET maxmemory-policy
最易被忽略的一点:Laravel 队列任务反序列化依赖 APP_KEY。换环境部署时若 APP_KEY 不一致,Redis 里存的任务无法解包,会静默失败——连日志都不打。别只盯着 Redis 和进程,先核对 APP_KEY 是否统一。











