Yii2 配 Redis 队列需三点:任务类实现 JobInterface 且可序列化;Redis 配置须分 channel、加 LogBehavior、独立连接;消费用 Supervisor 多进程运行 queue/listen,配合 delay 和 retryLimit 控制延迟与重试。

用 Yii2 配 Redis 做队列,核心就三点:任务要可序列化、推送要走正规类、消费得靠常驻进程。不是写个 echo 就算异步,关键在结构和配置是否稳。
任务类必须独立且可序列化
别把发邮件、生成报表的逻辑直接塞进控制器里调 $queue->push() —— Yii 默认不支持序列化闭包,会报 Serialization of 'Closure' is not allowed。正确做法是新建一个 PHP 类,实现 JobInterface:
- 继承 BaseObject,确保属性能被序列化(不能含 PDO、Redis 实例等资源对象)
- 所有业务逻辑写在 execute($queue) 方法内
- 依赖通过构造参数注入(如
public function __construct(private MailService $mailer) { ... }),避免硬编码 - 命名空间与文件路径严格匹配,保证自动加载正常
Redis 队列配置要带日志和通道隔离
光配好 redis 连接还不够,生产环境必须加行为和分组。推荐配置如下:
-
channel 按业务拆分,比如
'channel' => 'email'或'channel' => 'report',避免不同任务互相阻塞 - 加上 LogBehavior:
'as log' => \yii\queue\LogBehavior::class,自动记录 push/pop/failed 状态 - redis 连接单独配置,数据库连接复用已有组件,不要重复定义
- 若用 redis list + blpop 实现底层,它天然支持阻塞读,无消息时不会空轮询,延迟接近零
消费进程得用 Supervisor 多实例跑
php yii queue/listen 只启动一个 worker,串行处理。真要提速,必须靠多进程:
- 用 Supervisor 启多个
queue/listen进程,每个绑定不同--channel或共享同一 channel - 设置
numprocs=4、autostart=true、autorestart=true - 配合 retryLimit => 3,防止失败任务无限重试卡死队列
- 记得给每个进程分配独立 stdout/stderr 日志路径,方便排查
延迟任务和失败重试要主动控制
不是所有任务都立刻执行,也不是失败了就丢掉:
- 延迟投递用
delay(10):Yii::$app->queue->delay(10)->push(new SendEmailJob([...])) - 失败重试靠 retryLimit 控制次数,数据库驱动下默认是 -1(无限重试),建议设为 3 或 5
- Redis 驱动本身不内置重试计数,需配合 maxRetry => 3 等扩展参数或自定义 retry 逻辑
- 任务失败后,日志行为会记录错误堆栈,结合监控可快速定位问题环节


















