Laravel Redis队列需显式配置QUEUE_CONNECTION=redis并确保redis连接正确,否则任务在请求中直接执行;dispatch后未消费常见于未启动worker或队列名不匹配;失败任务不进failed_jobs表,重试依赖job类的$tries和config中redis.retry_after设置;大对象应传ID或JSON序列化避免内存暴涨。

队列驱动必须显式配置为 redis
默认 Laravel 配置下,QUEUE_CONNECTION 是 sync,任务根本不会进 Redis,而是在当前请求中直接执行——这看起来“成功”了,实则完全没走队列。必须改环境变量:
QUEUE_CONNECTION=redis- 确认
config/queue.php中redis连接配置指向了正确的REDIS_HOST和REDIS_PORT - 如果用的是 Laravel 9+,还要检查
database/redis.php是否存在且未被忽略(部分部署会删掉它)
dispatch() 后任务没进 queues:work 消费
常见错因不是代码写错,而是没启动消费者或队列名不匹配。Laravel 默认使用 default 队列,但如果你在 dispatch 时指定了其他队列名(比如 dispatch((new SendEmailJob)->onQueue('notifications'))),就必须手动指定 worker 监听:
- 运行
php artisan queue:work --queue=notifications,而不是只跑queue:work - 若用 Supervisor 管理进程,确保
command行里包含--queue=xxx - Redis 中实际队列键名是
queues:xxx,可用redis-cli KEYS "queues:*"验证有没有数据写入
任务失败后卡在 failed_jobs 表却不重试
Laravel 的 Redis 驱动默认不启用失败重试逻辑(和数据库驱动不同),一旦 job 抛出异常,就直接进 failed_jobs 表,不会自动重试。要控制重试行为,得靠两个地方:
- 在 job 类里定义
$tries = 3和$backoff = 5(单位秒),这是 Laravel 自己的重试机制,与 Redis TTL 无关 - 确保
config/queue.php中redis.retry_after设得足够长(比如90秒),否则 Redis 会在任务还在执行时就把它当“超时”踢出去,导致重复执行 - 别依赖
php artisan queue:retry all来救火——它只对数据库驱动的failed_jobs有效;Redis 驱动失败的任务压根不进这张表,得自己用redis-cli LPOP queues:default手动捞出来重发
大对象序列化进 Redis 导致内存暴涨或超时
PHP 序列化后的对象体积可能比原始数组大 2–3 倍,尤其含 Closure、Resource 或大量关联模型时。Redis 默认单 key 上限 512MB,但更现实的问题是网络传输慢、序列化耗 CPU:
- 永远不要在 job 构造函数里传
App\Models\User实例,改传$user->id,然后在handle()里重新查 - 避免在 job 属性里存
Illuminate\Http\UploadedFile,先保存到磁盘或 OSS,再传路径 - 如果必须传结构化数据,用
json_encode($data, JSON_UNESCAPED_UNICODE)替代 PHP serialize,体积小、跨语言友好、Redis 里也看得懂
事情说清了就结束。真正卡住人的往往不是语法,而是 redis.retry_after 和 $tries 的配合时机,还有那张根本不起作用的 failed_jobs 表。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











