Очереди задач — это как конвейер на заводе: вы кладёте задачу в начало, а где-то в другом месте её подхватывает рабочий и выполняет. В веб-разработке это позволяет разгрузить основной поток и не заставлять пользователя ждать, пока сервер досчитает что-то тяжёлое. Yii2 из коробки не имеет встроенной очереди, но есть официальное расширение yii2-queue, которое поддерживает Redis. В этой статье я расскажу, как подружить Yii2 с Redis и запустить очередь задач.

Digital-студия WNDER

Почему именно 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 — это имя очереди, можно использовать разные каналы для разных типов задач.

Правило: Никогда не используйте базу данных Redis, которую вы применяете для кеша, под очереди. Создайте отдельную базу (например, database => 1), чтобы случайная очистка кеша не уничтожила задачи.

Создание задачи

Задача — это обычный 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