Laravel 动态优先级调度可通过五种方法实现:一、MongoDB 驱动注入 priority 字段并联合排序;二、Redis 多键+路由策略分发至 high/medium/low 队列;三、Database 驱动重写 getNextAvailableJob 支持运行时 SQL 排序;四、Horizon 自定义 BalanceStrategy 动态伸缩 worker;五、任务类内嵌优先级中间件执行前升级队列。

如果您在 Laravel 应用中需要根据运行时条件(如用户等级、订单金额、系统负载)动态调整队列任务的执行优先级,则不能依赖静态队列名或预设 worker 进程顺序。Laravel 原生不提供 dispatch()->withPriority() 这类 API,但可通过多层策略组合实现真正动态的优先级调度。以下是可行的动态调整方法:
一、基于 MongoDB 驱动的动态优先级字段排序
该方法通过扩展 MongoQueue 类,在任务存储层注入 priority 字段,并在拉取任务时按 priority 降序 + available_at 升序联合排序,使高优先级任务始终被优先取出。
1、修改任务集合结构,在插入任务时写入 priority 字段(支持 1–10 整数):
2、定位 src/Queue/MongoQueue.php 中 getNextAvailableJobAndReserve 方法内的排序逻辑,将原 'sort' => ['available_at' => 1] 替换为:
'sort' => ['priority' => -1, 'available_at' => 1]
3、创建辅助分发函数 dispatchWithPriority(),在任务实例化时动态赋值 priority 属性:
4、在任务类中声明 public $priority = 5; 并确保 __construct() 或 handle() 前完成赋值,避免序列化后丢失。
二、Redis 多键+动态路由的运行时队列选择
该方法不修改 Laravel 核心队列驱动,而是利用 Redis 的多个 list 键与自定义路由逻辑,在任务分发时刻根据业务规则实时决定推送至 high、medium 或 low 键,再由独立 worker 按需消费。
1、定义路由策略函数,例如依据订单金额自动分配队列键:
if ($order->total > 10000) { $queueKey = 'queues:high'; } elseif ($order->total > 1000) { $queueKey = 'queues:medium'; } else { $queueKey = 'queues:low'; }
2、使用 Redis::lpush() 直接向目标键推送序列化任务数据,绕过默认 Queue::dispatch() 流程。
3、启动三个独立 worker 进程,分别监听对应键:
php artisan queue:work --queue=high
php artisan queue:work --queue=medium
php artisan queue:work --queue=low
4、为每个 worker 配置差异化参数:high 队列使用 --sleep=1 和 --max-jobs=100,low 队列使用 --sleep=5 和 --max-jobs=500。
Laravel Cloud(cloud.laravel.com)。此技能用于处理所有 Laravel Cloud 请求,包括搜索和读取数据。只要任务涉及 Laravel Cloud,即使用此技能。
三、数据库驱动下运行时 SQL 排序覆盖
当使用 database 驱动时,可通过重写 Illuminate\Queue\DatabaseQueue 的 getNextAvailableJob 方法,注入动态 WHERE 条件与 ORDER BY 子句,在每次拉取任务前根据当前系统状态(如 Redis 中的权重配置)计算优先级权重并排序。
1、新建 CustomDatabaseQueue 类继承 DatabaseQueue,重写 getNextAvailableJob 方法。
2、在排序子句中引入子查询或 JOIN,关联一个 priority_rules 表,该表存储 route_pattern、priority_weight、生效时间等字段。
3、在任务分发前,将业务上下文(如 user_id、event_type)写入临时缓存,供 getNextAvailableJob 读取并参与排序计算。
4、确保 jobs 表已添加 priority_weight 列,并在每次任务入队时触发 UPDATE 更新该字段值。
四、Horizon + 自定义 BalanceStrategy 动态伸缩
若已启用 Laravel Horizon,可编写自定义 BalanceStrategy 类,根据 Redis 中各队列 pending 任务数、平均处理时长、CPU 负载等指标,实时调整各队列 worker 分配数量,从而实现“高负载时自动增派 high 队列 worker”的动态优先级保障。
1、创建 App\Horizon\DynamicBalanceStrategy 类,实现 Illuminate\Horizon\Contracts\BalanceStrategy 接口。
2、在 balance() 方法中调用 Redis::llen('queues:high') 获取积压量,结合 DB::table('jobs')->where('queue', 'high')->avg('runtime') 计算历史耗时。
3、根据公式:target_workers = base_workers × (pending / threshold) × (1 + load_factor),动态返回各队列应分配的进程数。
4、在 config/horizon.php 的 'environments' 配置块中,将 'balance' 设置为 'custom',并指定 'strategy' => App\Horizon\DynamicBalanceStrategy::class。
五、任务类内嵌优先级决策中间件
该方法在任务执行链路中插入优先级判断逻辑,不改变入队行为,而是在任务被 worker 取出后、handle() 执行前,依据当前环境变量或配置中心值决定是否跳过、延迟或转投更高优先级队列。
1、定义任务基类 PriorityJob,实现 Illuminate\Contracts\Queue\ShouldQueue 接口,并在 __construct() 中初始化 $this->priorityRule。
2、在 handle() 方法开头插入检查逻辑:
if ($this->shouldUpgradePriority()) { $this->dispatch(new static($this->payload))->onQueue('high'); return; }
3、实现 shouldUpgradePriority(),从 config('queue.priority_upgrade_rules') 加载规则数组,匹配当前任务属性(如 $this->user->is_vip === true)。
4、确保该逻辑不引发无限递归,需设置升级标记字段(如 $this->upgraded = true)并在重投前校验。

















