Laravel用Redis做队列需确保三处正确:驱动配置指向真实Redis实例、任务分发传模型ID而非实例、worker必须用supervisor守护;否则易静默失败。
直接说结论:Laravel 用 Redis 做队列,不是配对就能跑通,关键在三处——驱动配置必须指向真实 Redis 实例、任务分发时别传 Eloquent 模型实例、worker 必须用 supervisor 长期守护,否则一关终端就停。
确认 Redis 连接是否真通,别被 .env 假象骗了
很多人改了 QUEUE_CONNECTION=redis 就以为完事,但 Laravel 会默认用 config/database.php 里 redis.default 的配置。如果本地装了 Redis 却没启动,或生产环境 Redis 地址/密码写错,dispatch() 看似成功,其实任务根本没进队列——连失败日志都不报,静默丢弃。
- 先手动测试连接:
php artisan tinker→Redis::ping(),返回"PONG"才算通 - 检查
config/queue.php中redis连接块的connection键是否和database.redis下实际定义的名字一致(比如你配的是cache,但 queue 里写default,就断开) - 如果用 PhpRedis 扩展(非 Predis),要确保
php -m | grep redis能看到redis,且config/queue.php中没硬编码依赖Predis
dispatch() 时传模型 ID,而不是模型对象本身
这是最常导致内存溢出或序列化失败的坑。Eloquent 模型带大量关联属性、访问器、原始查询状态,serialize() 它进 Redis 不仅慢,还可能因闭包、资源句柄等直接报错 Serialization of 'Closure' is not allowed。
- 错误写法:
SendEmailJob::dispatch($user)($user 是完整模型实例) - 正确写法:
SendEmailJob::dispatch($user->id),然后在handle()里重新查:$user = User::findOrFail($this->userId) - 如果实在要传模型,加
use SerializesModels;特质,并确保模型没加载太多关系(load()过的会全序列化)
queue:work 不能裸跑,必须用 supervisor 管着
php artisan queue:work 是个前台命令,关掉 SSH 就退出;哪怕加 --daemon,也扛不住内存泄漏、超时卡死、PHP 扩展崩溃——它不自动重启,任务就堆在队列里不动。