Skip to content
Icon

ПРЕДУПРЕЖДЕНИЕ Вы просматриваете документацию к старой версии Laravel. Рассмотрите возможность обновления Вашего проекта до Laravel 9.x.

Редис

Введение

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

Прежде чем использовать Redis с Laravel, мы рекомендуем вам установить и использовать расширение PHP phpredis через PECL. Расширение сложнее установить по сравнению с пакетами PHP «на уровне пользователя», но оно может обеспечить лучшую производительность для приложений, интенсивно использующих Redis. Если вы используете Laravel Sail, это расширение уже установлено в контейнере Docker вашего приложения.

Если вы не можете установить расширение phpredis, вы можете установить пакет predis/predis через Composer. Predis — это клиент Redis, полностью написанный на PHP и не требующий дополнительных расширений:

composer require 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, определенный в вашем файле конфигурации, должен иметь имя, хост и порт, если только вы не определите один URL-адрес для представления соединения Redis:

'redis' => [
 
'client' => env('REDIS_CLIENT', 'phpredis'),
 
'default' => [
'url' => 'tcp://127.0.0.1:6379?database=0',
],
 
'cache' => [
'url' => 'tls://user:password@127.0.0.1:6380?database=1',
],
 
],

Настройка схемы подключения

По умолчанию клиенты Redis будут использовать схему tcp при подключении к вашим серверам Redis; однако вы можете использовать шифрование TLS/SSL, указав параметр конфигурации scheme в массиве конфигурации вашего сервера Redis:

'redis' => [
 
'client' => env('REDIS_CLIENT', 'phpredis'),
 
'default' => [
'scheme' => 'tls',
'host' => env('REDIS_HOST', '127.0.0.1'),
'password' => env('REDIS_PASSWORD', null),
'port' => env('REDIS_PORT', 6379),
'database' => env('REDIS_DB', 0),
],
 
],

Кластеры

Если ваше приложение использует кластер серверов Redis, вы должны определить эти кластеры в ключе clusters вашей конфигурации Redis. Этот ключ конфигурации не существует по умолчанию, поэтому вам нужно будет создать его в файле конфигурации config/database.php вашего приложения:

'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.cluster на redis в файле конфигурации config/database.php вашего приложения:

'redis' => [
 
'client' => env('REDIS_CLIENT', 'phpredis'),
 
'options' => [
'cluster' => env('REDIS_CLUSTER', 'redis'),
],
 
'clusters' => [
// ...
],
 
],

Predis

Если вы хотите, чтобы ваше приложение взаимодействовало с Redis через пакет Predis, вы должны убедиться, что значение переменной среды REDIS_CLIENT равно predis:

'redis' => [
 
'client' => env('REDIS_CLIENT', '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,
],

Псевдоним фасада Redis

Конфигурационный файл config/app.php содержит массив aliases, который определяет все псевдонимы классов, которые будут зарегистрированы фреймворком. Для удобства запись псевдонима включена для каждого facade, предлагаемого Laravel; однако псевдоним Redis отключен, поскольку он конфликтует с именем класса Redis, предоставленным расширением phpredis. Если вы используете клиент Predis и хотите включить этот псевдоним, вы можете раскомментировать псевдоним в файле конфигурации config/app.php вашего приложения.

phpredis

По умолчанию Laravel будет использовать расширение phpredis для связи с Redis. Клиент, который Laravel будет использовать для связи с Redis, определяется значением параметра конфигурации redis.client, который обычно отражает значение переменной среды REDIS_CLIENT:

'redis' => [
 
'client' => env('REDIS_CLIENT', 'phpredis'),
 
// Rest of Redis configuration...
],

В дополнение к стандартным параметрам конфигурации сервера scheme, host, port, database и password поддерживает следующие дополнительные параметры подключения: name, persistent, persistent_id, prefix, read_timeout, retry_interval, timeoutи context. Вы можете добавить любой из этих параметров в конфигурацию вашего сервера 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,
'context' => [
// 'auth' => ['username', 'secret'],
// 'stream' => ['verify_peer' => false],
],
],

Сериализация и сжатие phpredis

Расширение phpredis также можно настроить для использования различных алгоритмов сериализации и сжатия. Эти алгоритмы можно настроить с помощью массива options вашей конфигурации Redis:

use Redis;
 
'redis' => [
 
'client' => env('REDIS_CLIENT', 'phpredis'),
 
'options' => [
'serializer' => Redis::SERIALIZER_MSGPACK,
'compression' => Redis::COMPRESSION_LZ4,
],
 
// Rest of Redis configuration...
],

В настоящее время поддерживаются следующие алгоритмы сериализации: Redis::SERIALIZER_NONE (по умолчанию), Redis::SERIALIZER_PHP, Redis::SERIALIZER_JSON, Redis::SERIALIZER_IGBINARY и Redis::SERIALIZER_MSGPACK.

Поддерживаемые алгоритмы сжатия включают: Redis::COMPRESSION_NONE (по умолчанию), Redis::COMPRESSION_LZF, Redis::COMPRESSION_ZSTD и Redis::COMPRESSION_LZ4.

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

Вы можете взаимодействовать с Redis, вызывая различные методы на Redis facade. Фасад 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 \Illuminate\Http\Response
*/
public function show($id)
{
return view('user.profile', [
'user' => Redis::get('user:profile:'.$id)
]);
}
}

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

use Illuminate\Support\Facades\Redis;
 
Redis::set('name', 'Taylor');
 
$values = Redis::lrange('names', 5, 10);

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

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

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

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

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

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

$redis = Redis::connection();

Транзакции

Метод Redis фасада transaction обеспечивает удобную оболочку вокруг собственных Redis команд MULTI и EXEC. Метод transaction принимает замыкание в качестве единственного аргумента. Это замыкание получит экземпляр подключения Redis и может выполнять любые команды, которые он хотел бы использовать для этого экземпляра. Все команды Redis, выпущенные в рамках замыкания, будут выполняться в одной атомарной транзакции:

use Illuminate\Support\Facades\Redis;
 
Redis::transaction(function ($redis) {
$redis->incr('user_visits', 1);
$redis->incr('total_visits', 1);
});

{note} При определении транзакции Redis вы не можете получать какие-либо значения из соединения Redis. Помните, что ваша транзакция выполняется как единая атомарная операция, и эта операция не выполняется до тех пор, пока все ваше замыкание не завершит выполнение своих команд.

Lua-скрипты

Метод eval предоставляет еще один метод выполнения нескольких команд Redis в одной атомарной операции. Однако преимущество метода eval metсостоит в том, что он может взаимодействовать и проверять значения ключей Redis во время этой операции. Скрипты Redis написаны на языке программирования Lua.

Поначалу метод eval может показаться немного пугающим, но мы рассмотрим базовый пример, чтобы растопить лед. Метод eval принимает несколько аргументов. Во-первых, вы должны передать Lua-скрипт (в виде строки) методу. Во-вторых, вы должны передать количество ключей (в виде целого числа), с которыми взаимодействует скрипт. В-третьих, вы должны передать имена этих ключей. Наконец, вы можете передать любые другие дополнительные аргументы, к которым вам нужно получить доступ в вашем скрипте.

В этом примере мы будем увеличивать счетчик, проверять его новое значение и увеличивать второй счетчик, если значение первого счетчика больше пяти. Наконец, мы вернем значение первого счетчика:

$value = Redis::eval(<<<'LUA'
local counter = redis.call("incr", KEYS[1])
 
if counter > 5 then
redis.call("incr", KEYS[2])
end
 
return counter
LUA, 2, 'first-counter', 'second-counter');

{note} Пожалуйста, обратитесь к документации Redis для получения дополнительной информации о сценариях Redis.

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

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

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

Pub / Sub

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:

use Illuminate\Support\Facades\Redis;
 
Route::get('/publish', function () {
// ...
 
Redis::publish('test-channel', json_encode([
'name' => 'Adam Wathan'
]));
});

Wildcard подписки

Используя метод psubscribe, вы можете подписаться на подстановочный канал, что может быть полезно для перехвата всех сообщений на всех каналах. Имя канала будет передано в качестве второго аргумента предоставленному замыканию:

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