Настройка приоритезации задач в очереди (Priority Queue)
Представьте: 90% пользователей уходят с сайта, если письмо сброса пароля не приходит в течение 5 секунд. А ваша очередь забита 30-минутными отчётами. Результат — потеря клиентов и негатив. Мы сталкивались с этим в проекте с 150 000 активных пользователей: critical-задачи (сброс пароля, SMS-коды) стояли в одной очереди с экспортами. После внедрения приоритезации latency для critical упало с 30 секунд до 2 секунд — в 15 раз быстрее. Ниже — как мы это делаем.
За 5+ лет работы с очередями мы обработали более 50 проектов, от стартапов до enterprise. Наш подход — спроектировать модель приоритетов, настроить воркеры и защитить систему от голодания. Без лишних абстракций, только проверенные паттерны.
Почему приоритезация задач в очереди критична для производительности?
Без приоритезации все задачи обрабатываются в порядке поступления (FIFO). Это приводит к недопустимым задержкам для критических операций. Например, в high-traffic проекте каждые 100 мс задержки снижают конверсию на 7%. Наши клиенты после настройки приоритетов видят сокращение времени ответа critical-задач на 80–95%.
Модель приоритетов
Типичное разделение на три уровня:
| Очередь | Задачи | Допустимое ожидание |
|---|---|---|
critical |
Сброс пароля, SMS-коды, платёжные уведомления | < 5 секунд |
default |
Транзакционные письма, уведомления | < 30 секунд |
low |
Отчёты, экспорт, рассылки, индексация | минуты/часы |
Выбор уровней зависит от SLA вашего бизнеса. Для интернет-магазина можно добавить очередь high для заказов.
Как настроить приоритеты в Laravel?
Laravel поддерживает soft-приоритет: воркер перебирает очереди в указанном порядке. Команда:
php artisan queue:work --queue=critical,default,low Если в critical есть задачи, воркер не переходит к default. Приоритет задаётся при диспатче:
SendPasswordResetEmail::dispatch($user)->onQueue('critical'); Или внутри Job через свойство $queue. Это простой и быстрый способ, но при длинных задачах в low-очереди critical может ждать. Решение — выделенные воркеры Horizon.
Сравнение soft-приоритета и выделенных воркеров
| Параметр | Soft-приоритет | Выделенные воркеры (Horizon) |
|---|---|---|
| Latency для critical | Может достигать минут | Гарантировано < 5 секунд |
| Конфигурация | Один воркер | Supervisor на очередь |
| Риск starvation | Высокий при загрузке | Минимальный |
| Ресурсы | Экономичнее | Требует больше процессов |
Как использовать выделенные воркеры для критических задач?
Horizon позволяет создать отдельные пулы воркеров для каждой очереди. Сравните: soft-приоритет — latency для critical может достигать минут при загрузке low-очереди. Выделенные воркеры гарантируют < 5 секунд — в 10 раз быстрее. Пример конфигурации:
// config/horizon.php 'environments' => [ 'production' => [ 'critical-supervisor' => [ 'connection' => 'redis', 'queue' => ['critical'], 'balance' => 'simple', 'minProcesses' => 2, 'maxProcesses' => 8, 'timeout' => 30, ], 'default-supervisor' => [ 'connection' => 'redis', 'queue' => ['default'], 'balance' => 'auto', 'minProcesses' => 1, 'maxProcesses' => 5, 'timeout' => 60, ], 'low-supervisor' => [ 'connection' => 'redis', 'queue' => ['low'], 'balance' => 'simple', 'processes' => 2, 'timeout' => 3600, ], ], ], Каждый supervisor работает независимо: critical не блокируется low-задачами. Это стандартный паттерн для high-traffic проектов.
Что такое starvation и как его предотвратить?
Starvation (голодание) — ситуация, когда низкоприоритетные задачи никогда не обрабатываются из-за постоянного притока критических. Это приводит к бесконечному накоплению отчётов и экспортов. Два основных решения:
Aging — повышение приоритета со временем. Реализуем через scheduled job:
// повышаем приоритет задач, ожидающих более 30 минут Schedule::call(function () { Job::where('queue', 'low') ->where('created_at', '<', now()->subMinutes(30)) ->update(['queue' => 'default']); })->everyFifteenMinutes(); Выделенный воркер для low — один процесс гарантирует, что low-задачи рано или поздно выполнятся. Комбинация двух методов даёт 100% защиту.
Динамический приоритет на основе данных
Приоритет можно назначать не статически, а в зависимости от пользователя. Например, enterprise-клиентам — critical, обычным — default. Это гибче жёсткой схемы и экономит ресурсы.
Приоритет в BullMQ (Node.js)
BullMQ использует числовые приоритеты через Redis Sorted Set. Это точнее Laravel, но требует отдельной инфраструктуры.
await queue.add('send-password-reset', { userId: 123 }, { priority: 1 }); await queue.add('generate-report', { reportId: 789 }, { priority: 10 }); Чем меньше число, тем выше приоритет. В Laravel проще, если стек уже на PHP.
Мониторинг и алертинг
Глубину очередей отслеживаем через Redis: Redis::llen('queues:critical'). Horizon показывает это в дашборде. Настраиваем алерты на рост очередей — сигнал нехватки воркеров. Рекомендуем пороги: если critical > 50, default > 200 или low > 1000 — срочное оповещение. Это предотвращает простои.
Что входит в работу
- Аудит текущей архитектуры очередей
- Проектирование модели приоритетов с SLA
- Конфигурация воркеров (Horizon или BullMQ)
- Защита от голодания (aging + выделенный воркер)
- Мониторинг и документация
Сроки: базовая настройка трёх очередей — 3–5 часов. Логика антиголодания и мониторинг — ещё 2–4 часа. Стоимость рассчитывается индивидуально.
Оценим ваш проект — свяжитесь с нами. Закажите настройку очередей — получите консультацию по вашему стеку.
Подробнее о Laravel Horizon (официальная документация)







