Redis

Содержание:


Введение

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

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

Как альтернатива, вы можете установить расширение predis/predis через Composer:

composer require predis/predis
Predis был удалён автором компонента и может быть удалён из Ларавел в будующих выпусках.

Конфигурация

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

'redis' => [

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

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

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

],

Базовой конфигурации сервера должно хватить для разработки. Однако, вы можете свободно изменить массив основываясь на вашем окружени. Каждый сервер Redis, определённый в вашем файле конфигурации, требует следующих параметров: имя, хост и порт.

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

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

'redis' => [

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

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

],

По умолчанию, кластеры будут выполнять фрагментацию узлов на стороне клиента, что позволяет вам объединять узлы и создавать большой объём доступной оперативной памяти. Надо понимать, что фрагментация на стороне клиента не справляется с падениями, поэтому больше всего подходит для кэширования данных, которые доступны из другого первичного хранилища данных. Если вы хотите использовать собственную кластеризацию Redis, вам необходимо указать это в пункте options вашей конфигурации Redis:

'redis' => [

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

    'options' => [
        'cluster' => env('REDIS_CLUSTER', 'redis'),
    ],

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

],

Predis

Для того чтобы использовать расширение Predis вам необходимо изменить переменную среды REDIS_CLIENT с phpredis на predis:

'redis' => [

    'client' => env('REDIS_CLIENT', 'predis'),

    // Rest of Redis configuration...
],

Дополнительно к базовым опциями конфигурации сервера 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

Расширение PhpRedis настроено как базовый REDIS_CLIENT в вашем файле config/database.php:

'redis' => [

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

    // Rest of Redis configuration...
],

Если вы планируете использовать расширение PhpRedis вмести с фасадом Redis, вам стоит придумать другое имя, например code>RedisManager, чтобы избежать конфликта с классом Redis. Вы можете сделать это в секции псевдонимов вашего файла app.php.

'RedisManager' => Illuminate\Support\Facades\Redis::class,

Дополнительно к типовым host, port, database, и password опциям конфигурации сервера, PhpRedis поддерживает следующие дополнительные параметры соединения: persistent, prefix, read_timeout и timeout. Вы можете добавить любой из этим параметров в ваш файл конфигурации 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

Чтобы избежать конфиликтов с самим расширением PHP Redis, вам необходимо переименовать или удалить фасад Illuminate\Support\Facades\Redis из вашего файла конфигурации app массива aliases. Ещё лучше поностью удалить этот фасад, а обращать только через указание полного имени класса при использовании расширения.


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

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

<?php

namespace App\Http\Controllers;

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

class UserController extends Controller
{
    /**
     * Show the profile for the given user.
     *
     * @param  int  $id
     * @return Response
     */
    public function showProfile($id)
    {
        $user = Redis::get('user:profile:'.$id);

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

Как было сказано выше, вы можете вызвать любую из команды Redis для одноименного фасада. Ларавел использует магические метогды для передачи команды в сервер 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();

Таким образом вы получите экземпляр типового сервера Redis. Вы можете также передать имя соединения или кластера в метод 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);
    }
});

Публикации и подписки

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

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

<?php

namespace App\Console\Commands;

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

class RedisSubscribe extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'redis:subscribe';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Subscribe to a Redis channel';

    /**
     * Execute the console command.
     *
     * @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;
});