Очереди задач — это как конвейер на заводе: вы кладёте задачу в начало, а где-то в другом месте её подхватывает рабочий и выполняет. В веб-разработке это позволяет разгрузить основной поток и не заставлять пользователя ждать, пока сервер досчитает что-то тяжёлое. Yii2 из коробки не имеет встроенной очереди, но есть официальное расширение yii2-queue, которое поддерживает Redis. В этой статье я расскажу, как подружить Yii2 с Redis и запустить очередь задач.
Почему именно Redis?
Redis — это быстрое хранилище данных в памяти. Оно идеально подходит для очередей: операции добавления и извлечения задач выполняются за микросекунды. К тому же Redis часто уже используется в проектах для кеширования, так что дополнительный сервер поднимать не придётся.
Сравним популярные бэкенды для очередей в Yii2:
| Бэкенд | Скорость | Надёжность | Сложность настройки |
|---|---|---|---|
| Redis | Очень высокая | Средняя (данные в памяти) | Низкая |
| RabbitMQ | Высокая | Высокая | Средняя |
| Database | Низкая | Высокая | Низкая |
Если вам нужна максимальная производительность и вы готовы мириться с тем, что при падении Redis задачи могут потеряться, Redis — отличный выбор.
Установка и настройка
Первым делом устанавливаем расширение через Composer:
composer require --prefer-dist yiisoft/yii2-queue
Затем настраиваем компонент в конфиге приложения (обычно config/main.php или config/web.php). Добавляем в массив компонентов:
'components' => [
'queue' => [
'class' => \yii\queue\redis\Queue::class,
'host' => 'localhost',
'port' => 6379,
'database' => 0,
'channel' => 'default',
],
],
Здесь host и port — адрес вашего Redis-сервера. channel — это имя очереди, можно использовать разные каналы для разных типов задач.
Создание задачи
Задача — это обычный PHP-класс, который реализует интерфейс yii\queue\JobInterface. В методе execute() вы пишете то, что должно выполниться в фоне. Например, отправка email:
namespace app\jobs;
use yii\base\BaseObject;
use yii\queue\JobInterface;
class SendEmailJob extends BaseObject implements JobInterface
{
public $email;
public $subject;
public $body;
public function execute($queue)
{
// Здесь логика отправки письма
Yii::$app->mailer->compose()
->setTo($this->email)
->setSubject($this->subject)
->setTextBody($this->body)
->send();
}
}
Чтобы добавить задачу в очередь, используем компонент queue:
Yii::$app->queue->push(new SendEmailJob([
'email' => 'user@example.com',
'subject' => 'Привет',
'body' => 'Текст письма',
]));
Всё, задача улетела в Redis. Теперь её нужно выполнить.
Запуск обработчика
Обработчик — это консольная команда, которая слушает очередь и выполняет задачи. Yii2-queue предоставляет готовую команду queue/listen. Запускаем её из терминала:
yii queue/listen
Она будет работать в бесконечном цикле, извлекая задачи из Redis и выполняя их. Для продакшена лучше использовать супервизор (supervisor), чтобы процесс автоматически перезапускался при падении.
Если нужно выполнить все накопленные задачи и выйти, используйте:
yii queue/run
yii queue/listen --verbose=1 — тогда в консоль будет выводиться информация о каждой задаче.
Обработка ошибок и повторные попытки
Задачи могут падать: то Redis отвалится, то внешний API вернёт ошибку. По умолчанию yii2-queue пытается выполнить задачу 3 раза. Настроить это можно в конфиге компонента:
'queue' => [
'class' => \yii\queue\redis\Queue::class,
// ... другие настройки
'attempts' => 5, // количество попыток
'ttr' => 300, // время на выполнение задачи в секундах
],
Если задача исчерпала все попытки, она помечается как неудачная и попадает в отдельную очередь (failed). Посмотреть список таких задач можно командой:
yii queue/info
А повторить все неудачные — так:
yii queue/retry all
Практические советы
- Используйте разные каналы для разных типов задач. Например,
emailиimport. Так вы сможете запускать отдельные обработчики и балансировать нагрузку. - Следите за памятью. Если обработчик работает долго, PHP может утечь по памяти. Периодически перезапускайте процесс (например, через supervisor).
- Логируйте. Добавьте в задачу запись в лог о начале и завершении. Это поможет отладить, если что-то пойдёт не так.
- Не храните в Redis важные данные без персистентности. Настройте AOF или RDB, чтобы задачи не потерялись при перезагрузке сервера.
ttr (time to reserve) больше, чем максимальное время выполнения задачи. Иначе Yii2 может посчитать, что задача зависла, и передать её другому обработчику.
Заключение
Очереди задач на Redis в Yii2 — это просто и эффективно. Вы добавляете задачу в очередь, а фоновый процесс её выполняет. Это ускоряет отклик сайта и делает систему более устойчивой. Главное — не забывайте про обработку ошибок и мониторинг. Надеюсь, статья была полезной. Удачи в разработке!
Студия WNDER
