Redis

Введение

Redis - хранилище пар ключ/значение с расширенным функционалом и открытым исходным кодом. Его часто называют сервисом структур данных, так как ключи могут содержать строки, хэши, списки, наборы и сортированные наборы.

Чтобы начать использовать Redis с Laravel, необходимо либо установить пакет predis/predis с помощью Composer:

composer require predis/predis

Либо, вы можете установить расширение для PHP PhpRedis через PECL. Расширение сложнее установить, но оно даёт большую производительность для приложений, которые активно используют Redis.

Настройка

Настройки вашего подключения к Redis хранятся в конфиге config/database.php. В нём вы найдёте массив redis, содержащий список серверов, используемых приложением:

'redis' => [

    'client' => 'predis',

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

],

Значения по умолчанию должны подойти для разработки. Однако вы свободно можете изменять этот массив в зависимости от своей среды. У каждого сервера Redis, определённого в конфиге, должны быть имя, хост и порт.

Настройка кластеров

Если ваше приложение использует кластер серверов Redis, вы должны задать эти кластеры в ключе clusters своей настройки Redis:

'redis' => [

    'client' => 'predis',

    'clusters' => [
        'default' => [
            [
                'host' => env('REDIS_HOST', 'localhost'),
                'password' => env('REDIS_PASSWORD', null),
                'port' => env('REDIS_PORT', 6379),
                'database' => 0,
            ],
        ],
    ],

],

По умолчанию кластеры будут выполнять фрагментацию узлов Redis (client-side sharding), что позволит вам обращаться к ним и увеличить доступную RAM. Однако заметьте, что фрагментация не справляется с падениями, поэтому она в основном используется для кэшировании данных, которые доступны из основного источника. Если вы хотите использовать нативную кластеризацию Redis, то вам нужно указать ключ options в своей настройке Redis:

'redis' => [

    'client' => 'predis',

    'options' => [
        'cluster' => 'redis',
    ],

    'clusters' => [
        // ...
    ],

],

Predis

Помимо стандартных опций настройки сервера host, port, database и password Predis поддерживает дополнительные параметры подключения , которые можно определить для каждого из ваших серверов Redis. Чтобы использовать эти дополнительные опции, просто добавьте их в конфиг вашего сервера Redis - config/database.php:

'default' => [
    'host' => env('REDIS_HOST', 'localhost'),
    'password' => env('REDIS_PASSWORD', null),
    'port' => env('REDIS_PORT', 6379),
    'database' => 0,
    'read_write_timeout' => 60,
],

PhpRedis

{note} Если ваше расширение Redis установлено через PECL, вам нужно переименовать псевдоним для Redis в файле config/app.php.

Чтобы использовать расширение PhpRedis, вы должны задать опции client в конфигурации Redis значение phpredis. Эта опция находится в файле config/database.php:

'redis' => [

    'client' => 'phpredis',

    // Остальные настройки Redis...
],

Помимо стандартных опций настройки сервера host, port, database и password PhpRedis поддерживает следующие дополнительные параметры подключения: persistent, prefix, read_timeout и timeout. Вы можете добавить любые из этих опций в настройки своего сервера Redis в конфиге config/database.php:

'default' => [
    'host' => env('REDIS_HOST', 'localhost'),
    'password' => env('REDIS_PASSWORD', null),
    'port' => env('REDIS_PORT', 6379),
    'database' => 0,
    'read_timeout' => 60,
],

Взаимодействие с Redis

Вы можете взаимодействовать с Redis, вызывая различные методы фасада Redis. Фасад Redis поддерживает динамические методы, а значит вы можете вызвать любую Redis-команду на фасаде, и команда будет передана прямо в Redis. В этом примере мы вызовем Redis-команду GET с помощью вызова метода get фасада Redis:

<?php

namespace App\Http\Controllers;

use Illuminate\Support\Facades\Redis;
use App\Http\Controllers\Controller;

class UserController extends Controller
{
    /**
     * Показать профиль данного пользователя.
     *
     * @param  int  $id
     * @return Response
     */
    public function showProfile($id)
    {
        $user = Redis::get('user:profile:'.$id);

        return view('user.profile', ['user' => $user]);
    }
}

Как уже было сказано, вы можете вызывать любые Redis-команды фасада Redis. использует магические методы PHP для передачи команд на сервер Redis, поэтому просто передайте необходимые аргументы Redis-команде:

Redis::set('name', 'Taylor');

$values = Redis::lrange('names', 5, 10);

В качестве альтернативы вы можете передавать команды на сервер методом command, который принимает первым аргументом имя команды, а вторым — массив значений:

$values = Redis::command('lrange', ['name', 5, 10]);

Использование нескольких подключений Redis

Вы можете получить экземпляр Redis методом Redis::connection:

$redis = Redis::connection();

Так вы получите экземпляр подключения по умолчанию. Вы также можете передать имя подключения или кластера методу connection, чтобы получить определенный сервер или кластер, как определено в вашем файле настроек Redis:

$redis = Redis::connection('my-connection');

Конвейер команд

Конвейер должен использоваться, когда вы отправляете много команд на сервер за одну операцию. Метод pipeline принимает один аргумент - функцию-замыкание, которая получает экземпляр Redis. Вы можете выполнить все ваши команды на этом экземпляре Redis, и все они будут выполнены в рамках одной операции:

Redis::pipeline(function ($pipe) {
    for ($i = 0; $i < 1000; $i++) {
        $pipe->set("key:$i", $i);
    }
});

Pub / Sub

Laravel предоставляет удобный интерфейс к Redis-командам publish и subscribe. Эти команды позволяют прослушивать сообщения на заданном "канале". Вы можете публиковать сообщения в канал из другого приложения или даже при помощи другого языка программирования, что обеспечивает простую связь между приложениями и процессами.

Сначала давайте настроим слушатель канала с помощью метода subscribe. Мы поместим вызов этого метода в Artisan-команду, так как вызов метода subscribe запускает длительный процесс:

<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;
use Illuminate\Support\Facades\Redis;

class RedisSubscribe extends Command
{
    /**
     * Название и сигнатура команды консоли.
     *
     * @var string
     */
    protected $signature = 'redis:subscribe';

    /**
     * Описание команды консоли.
     *
     * @var string
     */
    protected $description = 'Subscribe to a Redis channel';

    /**
     * Выполнение команды консоли.
     *
     * @return mixed
     */
    public function handle()
    {
        Redis::subscribe(['test-channel'], function ($message) {
            echo $message;
        });
    }
}

Теперь мы можем публиковать сообщения в канал методом publish:

Route::get('publish', function () {
    // Route logic...

    Redis::publish('test-channel', json_encode(['foo' => 'bar']));
});

Подписка по маске

С помощью метода psubscribe вы можете подписаться на канал по маске, это может быть полезно для отлова всех сообщений на всех каналах. Название канала $channel будет передано вторым аргументом в предоставляемую функцию-замыкание:

Redis::psubscribe(['*'], function ($message, $channel) {
    echo $message;
});

Redis::psubscribe(['users.*'], function ($message, $channel) {
    echo $message;
});