Redis

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

Для работы с Redis, вы можете использовать один из двух драйверов:

  1. PhpRedis (рекомендуется) — PHP-расширение, обеспечивающее лучшую производительность
  2. Predis — PHP-пакет, устанавливаемый через Composer:
composer require predis/predis
BASH

Конфигурирование

Базовая конфигурация Redis соедениений настраивается в файле config/database.php:

'redis' => [
    // Выбор клиента: 'phpredis' (по умолчанию) или 'predis'
    'client' => env('REDIS_CLIENT', 'phpredis'),
    
    // Глобальные опции для всех подключений
    'options' => [
        // Режим кластеризации
        'cluster' => env('REDIS_CLUSTER', 'redis'),
        // Префикс для всех ключей
        'prefix' => env('REDIS_PREFIX', 'myapp_database_'),
        // Сериализатор (только для PhpRedis)
        'serializer' => Redis::SERIALIZER_PHP,
        // Сжатие (только для PhpRedis)
        'compression' => Redis::COMPRESSION_LZ4,
    ],
    
    // Основное подключение
    'default' => [
        'host' => env('REDIS_HOST', '127.0.0.1'),
        'password' => env('REDIS_PASSWORD', null),
        'port' => env('REDIS_PORT', 6379),
        'database' => env('REDIS_DB', 0),
        'timeout' => 5.0, // сек
        'retry_interval' => 100, // мс
        'persistent' => false,
        'persistent_id' => null,
        'read_timeout' => 3.0, // только для Predis
    ],
    
    // Подключение для кэша (отдельная БД)
    '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),
        'timeout' => 3.0,
    ],
],
PHP

Работа с кластерами

'redis' => [
    'client' => 'phpredis',
    
    'options' => [
        'cluster' => 'redis',
        'timeout' => 5.0,
        'read_timeout' => 3.0,
        'failover' => RedisCluster::FAILOVER_ERROR,
        'persistent' => false,
    ],
    
    'clusters' => [
        'default' => [
            [
                'host' => 'redis-node1',
                'port' => 6379,
                'database' => 0,
                'password' => 'secret',
            ],
            [
                'host' => 'redis-node2',
                'port' => 6379,
                'database' => 0,
                'password' => 'secret',
            ],
            [
                'host' => 'redis-node3',
                'port' => 6379,
                'database' => 0,
                'password' => 'secret',
            ],
        ],
    ],
],
PHP

Подключение к Redis

Для получения экземпляра менеджера Redis, используйте соответствующий фасад:

use Imhotep\Facades\Redis;

// Получение подключения по умолчанию (default)
$redis = Redis::connection();

// Получение именованного подключения
$redisCache = Redis::connection('cache');
PHP

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

Фасад Redis за счет поддержки динамических методов, позволяет вызывать любую команду Redis.

Базовые операции

use Imhotep\Facades\Redis;

// SET / GET
Redis::set('user:1:name', 'John Doe');
$name = Redis::get('user:1:name');

// GETSET (установить и получить старое значение)
$oldValue = Redis::getSet('user:1:name', 'Jane Doe');

// EXISTS
if (Redis::exists('user:1:name')) {
    // Ключ существует
}

// DEL (удаление)
Redis::del(['user:1:name', 'user:1:email']);

// EXPIRE (установка времени жизни)
Redis::expire('user:1:session', 3600);

// TTL (получение времени жизни)
$ttl = Redis::ttl('user:1:session');

// INCR / DECR (инкремент/декремент)
Redis::incr('counter');
Redis::incrBy('counter', 10);
Redis::decr('counter');
PHP

При необходимости, можно передавать прямые команды на сервер Redis, используя метод Redis::command(...), где первым аргументом передается имя команды, а вторым массив параметром:

$values = Redis::command('lrange', ['name', 5, 10]);
// Эквивалентно
$values = Redis::lrange('queue', 5, 10);
PHP

Работа со списками

// LPUSH / RPUSH
Redis::lpush('queue', 'task1', 'task2');
Redis::rpush('queue', 'task3');

// LPOP / RPOP
$task = Redis::lpop('queue');

// LRANGE
$tasks = Redis::lrange('queue', 0, -1); // Получить все элементы
PHP

Работа с хешами

// HSET / HGET
Redis::hset('user:1', 'name', 'John');
Redis::hset('user:1', 'email', 'john@example.com');
$name = Redis::hget('user:1', 'name');

// HGETALL
$user = Redis::hgetall('user:1');

// HMSET / HMGET
Redis::hmset('user:1', ['age' => 30, 'city' => 'New York']);
$data = Redis::hmget('user:1', ['age', 'city']);
PHP

Работа с множествами

// SADD / SMEMBERS
Redis::sadd('tags', 'php', 'laravel', 'redis');
$tags = Redis::smembers('tags');

// SISMEMBER
if (Redis::sismember('tags', 'php')) {
    // Тег существует
}
PHP

Работа с сортированными множествами

// ZADD
Redis::zadd('leaderboard', 100, 'user:1');
Redis::zadd('leaderboard', 85, 'user:2', 95, 'user:3');

// ZREVRANGE (топ-3)
$top3 = Redis::zrevrange('leaderboard', 0, 2, 'WITHSCORES');

// ZINCRBY
Redis::zincrby('leaderboard', 10, 'user:1');
PHP

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

// Публикация
Redis::publish('channel:1', 'Hello, World!');

// Подписка (лучше через консольную команду)
Redis::subscribe(['channel:1', 'channel:2'], function($message, $channel) {
    echo "Получено сообщение '{$message}' из канала '{$channel}'";
});
PHP

Работа с транзакциями

// MULTI / EXEC
Redis::multi();
Redis::set('key1', 'value1');
Redis::set('key2', 'value2');
$result = Redis::exec(); // [true, true]
PHP

Lua скрипты

$script = "
    local current = redis.call('GET', KEYS[1]) or 0
    current = current + ARGV[1]
    redis.call('SET', KEYS[1], current)
    return current
";

$newValue = Redis::eval($script, 1, 'counter', 5);
PHP

Конвейерные операции (Pipeline)

Для повышения производительности при множественных операциях используйте конвейер:

use Imhotep\Facades\Redis;

$results = Redis::pipeline(function($pipe) {
    $pipe->set('key1', 'value1');
    $pipe->set('key2', 'value2');
    $pipe->get('key1');
    $pipe->get('key2');
});
PHP

События

Каждая выполненная команда генерирует событие Imhotep\Redis\Events\CommandExecuted:

use Imhotep\Facades\Redis;

// Подписка на события
Redis::listen(function($event) {
    Log::debug("Выполнена Redis команда: {$event->command}", [
        'parameters' => $event->parameters,
        'time' => $event->time,
        'connection' => $event->connectionName
    ]);
});

// Отключение событий (для повышения производительности)
Redis::disableEvents();

// Включение событий
Redis::enableEvents();
PHP

Макросы

Расширение функциональности через макросы:

use Imhotep\Facades\Redis;

Redis::macro('incrementAndGet', function($key, $by = 1) {
    return Redis::incrBy($key, $by);
});

$newValue = Redis::incrementAndGet('counter', 5);
PHP