必须确认驱动已生效,检查default与connections中键名严格匹配;启动work命令需指定--queue、--tries等参数;fire方法须手动调用$job->delete()或$job->release();Redis下关注reserved/delayed链表及retry_after设置。

队列任务执行前必须确认驱动已生效
ThinkPHP5 的 queue:work 命令不会自动校验配置是否真正生效,很多任务“看似入队成功”却始终不消费,根源是 default 驱动未正确指向你配置的连接(比如写了 'default' => 'redis',但 connections.redis 缺失或拼写错误)。检查方式很简单:在命令行执行 php think queue:failed,如果报错 Driver [xxx] not supported 或返回空列表但实际有任务堆积,大概率是驱动名/配置键不匹配。
常见错配点包括:
-
config/queue.php中的'default' => 'redis'和'connections'['redis']必须严格对应,不能写成'redis_conn'或漏掉connections顶层键 - 使用环境变量时(如
Env::get('queue.CONNECTOR')),确保.env文件里写了QUEUE_CONNECTOR=redis,且未被其他配置覆盖 - 若用
topthink/think-queue旧版(非 Laravel Queue 兼容层),驱动名是'connector'而非'driver',配置结构完全不同
启动消费者进程要带明确队列名和重试参数
直接运行 php think queue:work 默认只监听 default 队列,且不设失败重试逻辑——这意味着一旦某个任务抛出未捕获异常,它会立刻进入 failed_jobs 表(database)或永久卡在 Redis 的 reserved 状态(redis),后续不再尝试。必须显式指定参数:
- 监听特定队列:
php think queue:work --queue=send_email,notify_sms(多个用逗号分隔) - 设置单任务最大重试次数:
--tries=3,避免无限循环消耗资源 - 控制空闲时休眠时间:
--sleep=3(秒),防止 CPU 空转;Redis 驱动下低于 1 秒意义不大 - 启用内存限制保护:
--memory=128(MB),超限自动重启进程,防内存泄漏累积
生产环境务必用进程管理工具(如 Supervisor)守护,不要裸跑前台命令。
立即学习“PHP免费学习笔记(深入)”;
Job 类里的 fire 方法必须手动清理任务状态
ThinkPHP5 的 think-queue 不像 Laravel 那样自动调用 $job->delete(),如果你在 fire 方法里没显式删除,任务会一直留在队列中,下次轮询又执行一遍——造成重复消费。典型错误写法:
public function fire(Job $job, $data)
{
send_email($data['to'], $data['content']); // 执行完就结束
}
正确做法是:成功后删任务,失败时按需释放重试:
- 成功路径:
$job->delete(); - 临时失败需重试:
$job->release(60);(60 秒后重回队列) - 彻底失败(如参数非法):
$this->failed($job, $data);并在该方法里记录日志或告警
注意:$job->attempts() 返回当前已尝试次数,可用于控制重试上限,避免死循环。
Redis 驱动下任务堆积要查 reserved 和 delayed 链表
Redis 驱动的任务状态分散在多个 key 中:queues:default(待处理)、queues:default:reserved(正在执行)、queues:default:delayed(延迟任务)。当发现任务“入队后不执行”,先用 redis-cli 连上去检查:
-
LLEN queues:default:值为 0 但任务应存在 → 入队失败或投递到其他队列名 -
LLEN queues:default:reserved:值持续 > 0 → 消费者进程卡死或崩溃,未正常释放任务 -
ZCARD queues:default:delayed:值很大但无延迟任务 →retry_after设置过短,任务反复被标记为“超时”并重入reserved
紧急清理可执行 DEL queues:default:reserved,但必须确保所有消费者已停止,否则可能造成状态错乱。
Redis 驱动的 retry_after 参数(默认 90 秒)必须大于单个任务最长执行时间,否则未完成的任务会被误判为失败并重复执行——这是高并发下最隐蔽的重复问题来源。



















