はじめに
Redisはオープンソースの高度なキー・バリューストアです。キーにはstring、hashes、lists、sets、およびsorted setsを含むことができるため、データ構造サーバーとも呼ばれます。
LaravelでRedisを使用する前に、PECLを介してPhpRedis PHP拡張をインストールして使用することをお勧めします。この拡張は「ユーザーランド」PHPパッケージに比べてインストールが複雑ですが、Redisを多用するアプリケーションに対してはより良いパフォーマンスを発揮する可能性があります。Laravel Sailを使用している場合、この拡張はすでにアプリケーションのDockerコンテナにインストールされています。
PhpRedis拡張をインストールできない場合は、Composerを介してpredis/predis
パッケージをインストールできます。Predisは完全にPHPで書かれたRedisクライアントで、追加の拡張は必要ありません:
composer require predis/predis:^2.0
設定
アプリケーションのRedis設定は、config/database.php
設定ファイルを介して構成できます。このファイル内には、アプリケーションで使用されるRedisサーバーを含むredis
配列が表示されます:
'redis' => [
'client' => env('REDIS_CLIENT', 'phpredis'),
'options' => [
'cluster' => env('REDIS_CLUSTER', 'redis'),
'prefix' => env('REDIS_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_').'_database_'),
],
'default' => [
'url' => env('REDIS_URL'),
'host' => env('REDIS_HOST', '127.0.0.1'),
'username' => env('REDIS_USERNAME'),
'password' => env('REDIS_PASSWORD'),
'port' => env('REDIS_PORT', '6379'),
'database' => env('REDIS_DB', '0'),
],
'cache' => [
'url' => env('REDIS_URL'),
'host' => env('REDIS_HOST', '127.0.0.1'),
'username' => env('REDIS_USERNAME'),
'password' => env('REDIS_PASSWORD'),
'port' => env('REDIS_PORT', '6379'),
'database' => env('REDIS_CACHE_DB', '1'),
],
],
設定ファイルに定義された各Redisサーバーには、名前、ホスト、およびポートが必要です。単一のURLを定義してRedis接続を表す場合を除きます:
'redis' => [
'client' => env('REDIS_CLIENT', 'phpredis'),
'options' => [
'cluster' => env('REDIS_CLUSTER', 'redis'),
'prefix' => env('REDIS_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_').'_database_'),
],
'default' => [
'url' => 'tcp://127.0.0.1:6379?database=0',
],
'cache' => [
'url' => 'tls://user::6380?database=1',
],
],
接続スキームの設定
デフォルトでは、RedisクライアントはRedisサーバーに接続する際にtcp
スキームを使用します。ただし、Redisサーバーの設定配列にscheme
設定オプションを指定することで、TLS / SSL暗号化を使用することもできます:
'default' => [
'scheme' => 'tls',
'url' => env('REDIS_URL'),
'host' => env('REDIS_HOST', '127.0.0.1'),
'username' => env('REDIS_USERNAME'),
'password' => env('REDIS_PASSWORD'),
'port' => env('REDIS_PORT', '6379'),
'database' => env('REDIS_DB', '0'),
],
クラスター
アプリケーションがRedisサーバーのクラスターを利用している場合、Redis設定のclusters
キー内にこれらのクラスターを定義する必要があります。この設定キーはデフォルトでは存在しないため、アプリケーションのconfig/database.php
設定ファイル内に作成する必要があります:
'redis' => [
'client' => env('REDIS_CLIENT', 'phpredis'),
'options' => [
'cluster' => env('REDIS_CLUSTER', 'redis'),
'prefix' => env('REDIS_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_').'_database_'),
],
'clusters' => [
'default' => [
[
'url' => env('REDIS_URL'),
'host' => env('REDIS_HOST', '127.0.0.1'),
'username' => env('REDIS_USERNAME'),
'password' => env('REDIS_PASSWORD'),
'port' => env('REDIS_PORT', '6379'),
'database' => env('REDIS_DB', '0'),
],
],
],
// ...
],
デフォルトでは、Laravelはoptions.cluster
設定値がredis
に設定されているため、ネイティブRedisクラスターを使用します。Redisクラスターは、フェイルオーバーを優雅に処理するため、優れたデフォルトオプションです。
Laravelはクライアント側のシャーディングもサポートしています。ただし、クライアント側のシャーディングはフェイルオーバーを処理しないため、主に他のプライマリデータストアから利用可能な一時的なキャッシュデータに適しています。
ネイティブRedisクラスターの代わりにクライアント側のシャーディングを使用したい場合は、アプリケーションのconfig/database.php
設定ファイル内でoptions.cluster
設定値を削除できます:
'redis' => [
'client' => env('REDIS_CLIENT', 'phpredis'),
'clusters' => [
// ...
],
// ...
],
Predis
アプリケーションがPredisパッケージを介してRedisと対話するようにしたい場合は、REDIS_CLIENT
環境変数の値がpredis
であることを確認してください:
'redis' => [
'client' => env('REDIS_CLIENT', 'predis'),
// ...
],
デフォルトの設定オプションに加えて、Predisは各Redisサーバーに対して定義できる追加の[接続パラメータ](https://github.com/nrk/predis/wiki/Connection-Parametersをサポートしています。これらの追加の設定オプションを利用するには、アプリケーションの`````config/database.php`````設定ファイル内のRedisサーバー設定に追加してください:
'default' => [
'url' => env('REDIS_URL'),
'host' => env('REDIS_HOST', '127.0.0.1'),
'username' => env('REDIS_USERNAME'),
'password' => env('REDIS_PASSWORD'),
'port' => env('REDIS_PORT', '6379'),
'database' => env('REDIS_DB', '0'),
'read_write_timeout' => 60,
],
PhpRedis
デフォルトでは、LaravelはPhpRedis拡張を使用してRedisと通信します。LaravelがRedisと通信するために使用するクライアントは、redis.client
設定オプションの値によって決まります。この値は通常、REDIS_CLIENT
環境変数の値を反映します:
'redis' => [
'client' => env('REDIS_CLIENT', 'phpredis'),
// ...
],
デフォルトの設定オプションに加えて、PhpRedisは次の追加の接続パラメータをサポートしています: name
、persistent
、persistent_id
、prefix
、read_timeout
、retry_interval
、timeout
、およびcontext
。これらのオプションのいずれかをconfig/database.php
設定ファイル内のRedisサーバー設定に追加できます:
'default' => [
'url' => env('REDIS_URL'),
'host' => env('REDIS_HOST', '127.0.0.1'),
'username' => env('REDIS_USERNAME'),
'password' => env('REDIS_PASSWORD'),
'port' => env('REDIS_PORT', '6379'),
'database' => env('REDIS_DB', '0'),
'read_timeout' => 60,
'context' => [
// 'auth' => ['username', 'secret'],
// 'stream' => ['verify_peer' => false],
],
],
PhpRedisのシリアル化と圧縮
PhpRedis拡張は、さまざまなシリアライザーと圧縮アルゴリズムを使用するように設定することもできます。これらのアルゴリズムは、Redis設定のoptions
配列を介して構成できます:
'redis' => [
'client' => env('REDIS_CLIENT', 'phpredis'),
'options' => [
'cluster' => env('REDIS_CLUSTER', 'redis'),
'prefix' => env('REDIS_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_').'_database_'),
'serializer' => Redis::SERIALIZER_MSGPACK,
'compression' => Redis::COMPRESSION_LZ4,
],
// ...
],
現在サポートされているシリアライザーには、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
ファサード。Redis
ファサードは動的メソッドをサポートしており、ファサードで任意のRedisコマンドを呼び出すことができ、そのコマンドは直接Redisに渡されます。この例では、Redis
ファサードのget
メソッドを呼び出してRedisのGET
コマンドを呼び出します:
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Redis;
use Illuminate\View\View;
class UserController extends Controller
{
/**
* Show the profile for the given user.
*/
public function show(string $id): View
{
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);
または、Redis
ファサードのcommand
メソッドを使用してサーバーにコマンドを渡すこともできます。このメソッドは、最初の引数としてコマンドの名前を受け取り、2番目の引数として値の配列を受け取ります:
$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();
トランザクション
``````php
use Redis;
use Illuminate\Support\Facades;
Facades\Redis::transaction(function (Redis $redis) {
$redis->incr('user_visits', 1);
$redis->incr('total_visits', 1);
});
`
Redisトランザクションを定義する際には、Redis接続から値を取得することはできません。トランザクションは単一の原子的な操作として実行され、その操作はクロージャ全体がコマンドの実行を終えるまで実行されないことを忘れないでください。
Luaスクリプト
`````eval`````メソッドは最初は少し怖いかもしれませんが、基本的な例を探求して氷を破りましょう。`````eval`````メソッドは、いくつかの引数を期待します。最初に、Luaスクリプト(文字列として)をメソッドに渡す必要があります。次に、スクリプトが対話するキーの数(整数として)を渡す必要があります。3番目に、それらのキーの名前を渡す必要があります。最後に、スクリプト内でアクセスする必要がある他の追加の引数を渡すことができます。
この例では、カウンターをインクリメントし、その新しい値を検査し、最初のカウンターの値が5より大きい場合に2番目のカウンターをインクリメントします。最後に、最初のカウンターの値を返します:
``````php
$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');
`
Redisスクリプトに関する詳細情報は、Redisドキュメントを参照してください。
コマンドのパイプライン処理
時には、数十のRedisコマンドを実行する必要があるかもしれません。各コマンドのためにRedisサーバーにネットワークトリップを行う代わりに、pipeline
メソッドを使用できます。pipeline
メソッドは1つの引数を受け取ります: Redisインスタンスを受け取るクロージャです。このRedisインスタンスにすべてのコマンドを発行すると、すべてのコマンドが同時にRedisサーバーに送信され、サーバーへのネットワークトリップが削減されます。コマンドは発行された順序で実行されます:
use Redis;
use Illuminate\Support\Facades;
Facades\Redis::pipeline(function (Redis $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.
*/
public function handle(): void
{
Redis::subscribe(['test-channel'], function (string $message) {
echo $message;
});
}
}
次に、publish
メソッドを使用してチャネルにメッセージを公開できます:
use Illuminate\Support\Facades\Redis;
Route::get('/publish', function () {
// ...
Redis::publish('test-channel', json_encode([
'name' => 'Adam Wathan'
]));
});
ワイルドカードサブスクリプション
``````php
Redis::psubscribe(['*'], function (string $message, string $channel) {
echo $message;
});
Redis::psubscribe(['users.*'], function (string $message, string $channel) {
echo $message;
});
`