Разработка/ PHP/ Laravel

Redis в Laravel: варианты настройки проектов

Базовая схема

Для обычного Laravel-проекта на одном Redis-инстансе удобнее разделять данные по назначению: основное подключение, кэш, сессии и очереди. Это не даёт жёсткой изоляции, но сильно упрощает диагностику и очистку отдельных типов данных.

REDIS_DB=0
REDIS_CACHE_DB=1
REDIS_SESSION_DB=2
REDIS_QUEUE_DB=3

Такая схема хорошо читается: 0 — служебные ключи приложения, 1 — кэш, 2 — сессии, 3 — очереди.

Подключения в config/database.php

В стандартном Laravel-конфиге обычно уже есть default и cache. Для отдельных баз под сессии и очереди нужно добавить подключения session и queue в секцию redis.

'redis' => [
    'client' => env('REDIS_CLIENT', 'phpredis'),

    'options' => [
        'cluster' => env('REDIS_CLUSTER', 'redis'),
        'prefix' => env('REDIS_PREFIX', Str::slug((string) env('APP_NAME', 'laravel')).'-database-'),
        'persistent' => env('REDIS_PERSISTENT', false),
    ],

    'default' => [
        'host' => env('REDIS_HOST', '127.0.0.1'),
        'password' => env('REDIS_PASSWORD'),
        'port' => env('REDIS_PORT', '6379'),
        'database' => env('REDIS_DB', '0'),
    ],

    'cache' => [
        'host' => env('REDIS_HOST', '127.0.0.1'),
        'password' => env('REDIS_PASSWORD'),
        'port' => env('REDIS_PORT', '6379'),
        'database' => env('REDIS_CACHE_DB', '1'),
    ],

    'session' => [
        'host' => env('REDIS_HOST', '127.0.0.1'),
        'password' => env('REDIS_PASSWORD'),
        'port' => env('REDIS_PORT', '6379'),
        'database' => env('REDIS_SESSION_DB', '2'),
    ],

    'queue' => [
        'host' => env('REDIS_HOST', '127.0.0.1'),
        'password' => env('REDIS_PASSWORD'),
        'port' => env('REDIS_PORT', '6379'),
        'database' => env('REDIS_QUEUE_DB', '3'),
    ],
],

REDIS_SESSION_DB и REDIS_QUEUE_DB сами по себе ничего не переключают, пока в конфиге нет подключений, которые их читают.

.env для одного проекта

Для одного проекта без соседних сайтов на том же Redis-инстансе достаточно такой настройки:

REDIS_CLIENT=phpredis
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379

REDIS_DB=0
REDIS_CACHE_DB=1
REDIS_SESSION_DB=2
REDIS_QUEUE_DB=3

CACHE_STORE=redis
REDIS_CACHE_CONNECTION=cache

SESSION_DRIVER=redis
SESSION_CONNECTION=session

QUEUE_CONNECTION=redis
REDIS_QUEUE_CONNECTION=queue
REDIS_QUEUE=default

Если Redis защищён паролем:

REDIS_PASSWORD=СЛОЖНЫЙ_ПАРОЛЬ

После изменения .env:

php artisan config:clear
php artisan cache:clear
php artisan config:cache

Несколько сайтов на одном Redis

Когда один Redis-инстанс обслуживает несколько сайтов, я не начинаю нарезать каждому проекту свой набор баз 0/1/2/3, 4/5/6/7 и так далее. Практичнее оставить одинаковую ролевую схему баз и развести проекты по префиксам.

REDIS_PREFIX=my_project_prod_
CACHE_PREFIX=my_project_prod_cache_

SESSION_COOKIE=my_project_prod_session
REDIS_QUEUE=my_project_prod_default

REDIS_PREFIX отделяет Redis-ключи проекта, CACHE_PREFIX отдельно маркирует кэш Laravel, SESSION_COOKIE не даёт браузеру смешивать сессии соседних сайтов, а REDIS_QUEUE разводит имена очередей.

Имена для production

Префикс лучше делать явно: my_project_prod_, my_project_stage_. Короткие app_ и site_ быстро становятся бесполезными, когда проектов больше двух.

Пример для двух сайтов

Shop production

APP_NAME=shop

REDIS_DB=0
REDIS_CACHE_DB=1
REDIS_SESSION_DB=2
REDIS_QUEUE_DB=3

REDIS_PREFIX=shop_prod_
CACHE_PREFIX=shop_prod_cache_
SESSION_COOKIE=shop_prod_session
REDIS_QUEUE=shop_prod_default

CRM production

APP_NAME=crm

REDIS_DB=0
REDIS_CACHE_DB=1
REDIS_SESSION_DB=2
REDIS_QUEUE_DB=3

REDIS_PREFIX=crm_prod_
CACHE_PREFIX=crm_prod_cache_
SESSION_COOKIE=crm_prod_session
REDIS_QUEUE=crm_prod_default

Оба сайта используют одну и ту же ролевую карту баз, но ключи и очереди не пересекаются из-за префиксов.

Когда нужны отдельные Redis-инстансы

Отдельные Redis-инстансы нужны не для красоты конфигов, а для реальной изоляции. Я выношу проект или отдельный тип нагрузки в другой инстанс, когда требуется:

  • разная maxmemory-policy для кэша и очередей;
  • отдельный лимит памяти, который не делится с соседними сайтами;
  • высокая нагрузка на очереди или кэш;
  • жёсткая изоляция между проектами, окружениями или клиентами;
  • отдельный мониторинг, бэкапы или права доступа.

Разные Redis DB внутри одного инстанса не дают такой изоляции. Политика памяти, процесс Redis и общий лимит RAM остаются общими.

Проверка

Проверить кэш из Tinker:

php artisan tinker
Cache::put('redis_test', 'ok', 60);
Cache::get('redis_test');

Ожидаемый ответ — "ok".

Посмотреть ключи проекта:

redis-cli SCAN 0 MATCH 'my_project_prod_*'
redis-cli SCAN 0 MATCH 'my_project_prod_cache_*'

Если ключи не находятся, сначала проверяю php artisan config:clear и не остался ли старый кэш конфигурации.

Коротко

Для стандартного проекта: разные Redis DB под роли.

REDIS_DB=0
REDIS_CACHE_DB=1
REDIS_SESSION_DB=2
REDIS_QUEUE_DB=3

Для нескольких сайтов на одном Redis: префиксы и уникальные имена cookie/queue.

REDIS_PREFIX=my_project_prod_
CACHE_PREFIX=my_project_prod_cache_
SESSION_COOKIE=my_project_prod_session
REDIS_QUEUE=my_project_prod_default

Теги

Читать дальше