Skip to content

Redis

소개

Redis는 오픈 소스 고급 키-값 저장소입니다. 키가 문자열, 해시, 리스트, 세트정렬된 세트를 포함할 수 있기 때문에 종종 데이터 구조 서버라고도 합니다.

Laravel과 함께 Redis를 사용하기 전에 PECL을 통해 PhpRedis PHP 확장을 설치하고 사용하는 것이 좋습니다. 이 확장은 "user-land" 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 서버는 Redis 연결을 나타내는 단일 URL을 정의하지 않는 한 이름, 호스트 및 포트가 있어야 합니다:

'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:[email protected]: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 서버에 대해 정의할 수 있는 추가 연결 매개변수를 지원합니다. 이러한 추가 구성 옵션을 활용하려면 애플리케이션의 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은 Redis와 통신하기 위해 PhpRedis 확장을 사용합니다. Laravel이 Redis와 통신하는 데 사용할 클라이언트는 일반적으로 REDIS_CLIENT 환경 변수의 값을 반영하는 redis.client 구성 옵션의 값에 의해 결정됩니다:

'redis' => [
 
'client' => env('REDIS_CLIENT', 'phpredis'),
 
// ...
],

기본 구성 옵션 외에도 PhpRedis는 name, persistent, persistent_id, prefix, read_timeout, retry_interval, timeoutcontext와 같은 추가 연결 매개변수를 지원합니다. 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_IGBINARYRedis::SERIALIZER_MSGPACK입니다.

지원되는 압축 알고리즘은 Redis::COMPRESSION_NONE (기본값), Redis::COMPRESSION_LZF, Redis::COMPRESSION_ZSTDRedis::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
{
/**
* 지정된 사용자의 프로필을 표시합니다.
*/
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 메서드를 사용하여 서버에 명령어를 전달할 수 있습니다. command 메서드는 명령어 이름을 첫 번째 인수로, 값의 배열을 두 번째 인수로 받습니다:

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

여러 Redis 연결 사용

애플리케이션의 config/database.php 구성 파일을 통해 여러 Redis 연결/서버를 정의할 수 있습니다. Redis 파사드의 connection 메서드를 사용하여 특정 Redis 연결에 대한 연결을 가져올 수 있습니다:

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

기본 Redis 연결의 인스턴스를 가져오려면 추가 인수 없이 connection 메서드를 호출할 수 있습니다:

$redis = Redis::connection();

트랜잭션

Redis 파사드의 transaction 메서드는 Redis의 네이티브 MULTIEXEC 명령어에 대한 편리한 래퍼를 제공합니다. transaction 메서드는 클로저를 유일한 인수로 받습니다. 이 클로저는 Redis 연결 인스턴스를 받으며 이 인스턴스에 원하는 명령어를 발행할 수 있습니다. 클로저 내에서 발행된 모든 Redis 명령어는 단일 원자적 트랜잭션으로 실행됩니다:

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

Redis 트랜잭션을 정의할 때 Redis 연결에서 값을 검색할 수 없습니다. 트랜잭션은 단일 원자적 연산으로 실행되며 해당 연산은 전체 클로저가 명령어 실행을 완료할 때까지 실행되지 않는다는 점을 기억하십시오.

Lua 스크립트

eval 메서드는 단일 원자적 연산으로 여러 Redis 명령어를 실행하는 또 다른 방법을 제공합니다. 그러나 eval 메서드는 해당 작업 중에 Redis 키 값을 상호 작용하고 검사할 수 있다는 이점이 있습니다. Redis 스크립트는 Lua 프로그래밍 언어로 작성됩니다.

eval 메서드는 처음에는 약간 무서울 수 있지만, 기본 예제를 살펴봄으로써 시작해 보겠습니다. eval 메서드는 여러 인수를 예상합니다. 첫 번째로 Lua 스크립트 (문자열)를 메서드에 전달해야 합니다. 두 번째로 스크립트가 상호 작용하는 키의 수 (정수)를 전달해야 합니다. 세 번째로 해당 키의 이름을 전달해야 합니다. 마지막으로 스크립트 내에서 액세스해야 하는 추가 인수를 전달할 수 있습니다.

이 예에서 우리는 카운터를 증가시키고, 새 값을 검사하고, 첫 번째 카운터 값이 5보다 크면 두 번째 카운터를 증가시킵니다. 마지막으로 첫 번째 카운터의 값을 반환합니다:

$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');
exclamation

Redis 스크립팅에 대한 자세한 내용은 Redis 설명서를 참조하십시오.

명령어 파이프라이닝

때로는 수십 개의 Redis 명령어를 실행해야 할 수도 있습니다. 각 명령어에 대해 Redis 서버로 네트워크 트립을 만드는 대신 pipeline 메서드를 사용할 수 있습니다. pipeline 메서드는 하나의 인수를 받습니다: 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 publishsubscribe 명령어에 대한 편리한 인터페이스를 제공합니다. 이러한 Redis 명령어를 사용하면 지정된 "채널"에서 메시지를 수신할 수 있습니다. 다른 애플리케이션에서 또는 다른 프로그래밍 언어를 사용하여 채널에 메시지를 게시할 수 있으므로 애플리케이션과 프로세스 간의 쉬운 통신이 가능합니다.

먼저 subscribe 메서드를 사용하여 채널 수신기를 설정해 보겠습니다. subscribe 메서드를 호출하면 장기 실행 프로세스가 시작되므로 이 메서드 호출을 Artisan 명령어 내에 배치합니다:

<?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 = 'Redis 채널 구독';
 
/**
* 콘솔 명령어를 실행합니다.
*/
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'
]));
});

와일드카드 구독

psubscribe 메서드를 사용하면 모든 채널의 모든 메시지를 포착하는 데 유용할 수 있는 와일드카드 채널을 구독할 수 있습니다. 채널 이름은 제공된 클로저에 두 번째 인수로 전달됩니다:

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