> ## Documentation Index
> Fetch the complete documentation index at: https://kawax.biz/llms.txt
> Use this file to discover all available pages before exploring further.

# Redis

> Laravel 应用中使用 Redis 进行缓存、会话、队列和 Pub/Sub 的配置与操作方法。

Redis 是一款内存型的键值存储，是 Laravel 众多功能的后端选择。
本文介绍从配置到操作，再到 Pub/Sub 的完整用法。

<CardGroup cols={3}>
  <Card title="缓存" icon="database" href="/zh/cache">
    将 Redis 作为缓存驱动
  </Card>

  <Card title="队列" icon="list" href="/zh/queues">
    将 Redis 作为队列驱动
  </Card>

  <Card title="广播" icon="radio" href="/zh/broadcasting">
    通过 Pub/Sub 实现实时通信
  </Card>
</CardGroup>

## 什么是 Redis

[Redis](https://redis.io) 是一款开源的高性能键值存储。
它支持字符串、哈希、列表、集合、有序集合等多种数据结构，因此也被称作数据结构服务器。

Laravel 中 Redis 通常用于以下用途。

```mermaid theme={null}
flowchart LR
    A["Laravel<br>应用"] --> B["Redis"]

    subgraph uses ["主要用途"]
        C["缓存<br>Cache"]
        D["会话<br>Session"]
        E["队列<br>Queue"]
        F["广播<br>Broadcasting"]
    end

    B --> C
    B --> D
    B --> E
    B --> F
```

## 选择客户端

Laravel 支持两种客户端：**PhpRedis**（PHP 扩展）和 **Predis**（PHP 库）。

| 项目           | PhpRedis       | Predis                   |
| ------------ | -------------- | ------------------------ |
| 实现           | 用 C 编写的 PHP 扩展 | 纯 PHP 库                  |
| 安装           | 需要 PECL 扩展     | 通过 `composer require` 完成 |
| 性能           | 更快             | 略慢于 PhpRedis             |
| Laravel Sail | 默认预装           | 需另行安装                    |
| 推荐场景         | 生产环境           | 开发环境或安装扩展受限时             |

<Info>
  Laravel 13 的默认客户端是 PhpRedis。生产环境推荐使用 PhpRedis。
  使用 Laravel Sail 时 PhpRedis 已经预装。
</Info>

## 配置

### config/database.php

Redis 的配置放在 `config/database.php` 的 `redis` 数组中。

```php theme={null}
'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'),
    ],

],
```

### 环境变量

在 `.env` 中配置连接信息。

```ini theme={null}
REDIS_CLIENT=phpredis
REDIS_HOST=127.0.0.1
REDIS_PORT=6379
REDIS_PASSWORD=null
REDIS_DB=0
REDIS_CACHE_DB=1
```

也支持使用 URL 形式配置。

```php theme={null}
'default' => [
    'url' => 'tcp://127.0.0.1:6379?database=0',
],

'cache' => [
    'url' => 'tls://user:password@127.0.0.1:6380?database=1',
],
```

### TLS / SSL 连接

若要使用 TLS 加密，请指定 `scheme` 选项。

```php theme={null}
'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 时使用 `clusters` 键。

```php theme={null}
'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'),
            ],
        ],
    ],

],
```

默认情况下 `options.cluster` 为 `redis`，使用原生的 Redis 集群模式，
它会自动处理故障切换，适合生产环境。

如果使用 Predis 的客户端侧分片，请删除 `options.cluster`。
但客户端侧分片不处理故障切换，只适合缓存等一次性数据。

### Predis 的配置

使用 Predis 需要安装 `predis/predis` 并把 `REDIS_CLIENT` 改为 `predis`。

```shell theme={null}
composer require predis/predis
```

```ini theme={null}
REDIS_CLIENT=predis
```

可以指定 Predis 特有的[连接参数](https://github.com/nrk/predis/wiki/Connection-Parameters)。

```php theme={null}
'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,
],
```

#### Predis 的重试设置

Predis 3.4.0 及以上版本内置了重试与退避设置。使用 `max_retries` 设置重试次数，`retry` 设置退避策略。`retry` 选项接收一个数组，其中键是 `NoBackoff`、`EqualBackoff` 或 `ExponentialBackoff` 的类名。

```php theme={null}
use Predis\Retry\Strategy\ExponentialBackoff;

'default' => [
    'url' => env('REDIS_URL'),
    // ...
    'retry' => [
        ExponentialBackoff::class => [
            env('REDIS_BACKOFF_BASE', 100),
            env('REDIS_BACKOFF_CAP', 1000),
            true, // 开启抖动
        ],
    ],
    'max_retries' => env('REDIS_MAX_RETRIES', 3),
],
```

在 Redis 集群下使用 Predis 时，通过集群设置里的 `parameters` 选项配置重试。

```php theme={null}
use Predis\Retry\Strategy\NoBackoff;

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

'options' => [
    'cluster' => env('REDIS_CLUSTER', 'redis'),
    'parameters' => [
        'retry' => [
            NoBackoff::class => [],
        ],
        'max_retries' => env('REDIS_MAX_RETRIES', 3),
    ],
],
```

### PhpRedis 的配置

PhpRedis 通过 PECL 安装（Laravel Sail 已预装）。
它还支持以下额外选项：
`name`、`persistent`、`persistent_id`、`prefix`、`read_timeout`、`retry_interval`、
`max_retries`、`backoff_algorithm`、`backoff_base`、`backoff_cap`、`timeout`、`context`。

```php theme={null}
'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],
    ],
],
```

#### 重试与退避设置

用来配置连接失败时的重试行为。
支持的退避算法有：`default`、`decorrelated_jitter`、`equal_jitter`、`exponential`、`uniform`、`constant`。

```php theme={null}
'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'),
    'max_retries' => env('REDIS_MAX_RETRIES', 3),
    'backoff_algorithm' => env('REDIS_BACKOFF_ALGORITHM', 'decorrelated_jitter'),
    'backoff_base' => env('REDIS_BACKOFF_BASE', 100),
    'backoff_cap' => env('REDIS_BACKOFF_CAP', 1000),
],
```

#### 使用 Unix 套接字

当 Redis 与应用在同一台机器上时，通过 Unix 套接字连接可以减少 TCP 开销。

```ini theme={null}
REDIS_HOST=/run/redis/redis.sock
REDIS_PORT=0
```

#### 序列化与压缩

PhpRedis 允许配置存储数据的序列化和压缩算法。

```php theme={null}
'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`      | PHP 原生序列化   |
| `Redis::SERIALIZER_JSON`     | JSON        |
| `Redis::SERIALIZER_IGBINARY` | igbinary    |
| `Redis::SERIALIZER_MSGPACK`  | MessagePack |

支持的压缩算法：

| 常量                        | 说明        |
| ------------------------- | --------- |
| `Redis::COMPRESSION_NONE` | 不压缩（默认）   |
| `Redis::COMPRESSION_LZF`  | LZF       |
| `Redis::COMPRESSION_ZSTD` | Zstandard |
| `Redis::COMPRESSION_LZ4`  | LZ4       |

## 与 Redis 交互

### Redis Facade

通过 `Redis` Facade 可以执行任何 Redis 命令。
Facade 通过魔术方法把命令转发给 Redis 服务器。

```php theme={null}
<?php

namespace App\Http\Controllers;

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)
        ]);
    }
}
```

带参数的命令直接以方法参数传入。

```php theme={null}
use Illuminate\Support\Facades\Redis;

Redis::set('name', 'Taylor');

$values = Redis::lrange('names', 5, 10);
```

也可以通过 `command` 方法显式指定命令名和参数。

```php theme={null}
$values = Redis::command('lrange', ['name', 5, 10]);
```

### 多连接切换

可以在 `config/database.php` 中定义多个 Redis 连接，通过 `connection()` 方法切换。

```php theme={null}
// 取指定名字的连接
$redis = Redis::connection('connection-name');

// 取默认连接
$redis = Redis::connection();
```

### 事务

`transaction()` 方法封装了 Redis 的 `MULTI`/`EXEC`。
闭包中的所有命令会原子地执行。

```php theme={null}
use Redis;
use Illuminate\Support\Facades;

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

<Warning>
  事务中无法从 Redis 读取值。
  因为整个闭包会在收到 `EXEC` 后一次性执行。
</Warning>

### Lua 脚本

`eval()` 方法可以原子性地执行 Lua 脚本。
比事务更灵活，脚本内可以引用与更新 Redis 中的值。

```php theme={null}
$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');
```

参数顺序：Lua 脚本 → 键数量 → 键名... → 附加参数...

`KEYS[1]`、`KEYS[2]` 是键名，`ARGV[1]` 起是附加参数。

### 管道（Pipeline）

一次性发送大量命令，可减少网络往返。

```php theme={null}
use Redis;
use Illuminate\Support\Facades;

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

```mermaid theme={null}
sequenceDiagram
    participant App as Laravel<br>应用
    participant Redis

    Note over App,Redis: 常规（每条命令都往返）
    App->>Redis: SET key:0 0
    Redis-->>App: OK
    App->>Redis: SET key:1 1
    Redis-->>App: OK

    Note over App,Redis: 管道（一次性发送）
    App->>Redis: SET key:0 0 / SET key:1 1 / ...
    Redis-->>App: OK / OK / ...
```

<Tip>
  管道只是打包发送命令，不保证原子性。
  如果需要原子性，请使用事务或 Lua 脚本。
</Tip>

## Pub / Sub

Redis 的 `publish` / `subscribe` 命令可用于通过频道传递消息。

### 订阅者

`subscribe()` 是一个长时间运行的过程，通常在 Artisan 命令中调用。

```php theme={null}
<?php

namespace App\Console\Commands;

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

class RedisSubscribe extends Command
{
    protected $signature = 'redis:subscribe';

    protected $description = 'Subscribe to a Redis channel';

    public function handle(): void
    {
        Redis::subscribe(['test-channel'], function (string $message) {
            echo $message;
        });
    }
}
```

### 发布者

从其他请求或进程中发送消息。

```php theme={null}
use Illuminate\Support\Facades\Redis;

Route::get('/publish', function () {
    Redis::publish('test-channel', json_encode([
        'name' => 'Adam Wathan'
    ]));
});
```

### 通配符订阅

使用 `psubscribe()` 可以按模式匹配进行订阅。

```php theme={null}
// 订阅所有频道
Redis::psubscribe(['*'], function (string $message, string $channel) {
    echo $message;
});

// 订阅 users.* 模式的频道
Redis::psubscribe(['users.*'], function (string $message, string $channel) {
    echo $message;
});
```

## 小结

<AccordionGroup>
  <Accordion title="客户端选择">
    * **生产环境**：PhpRedis（PECL 扩展，性能好）
    * **开发环境或不方便安装扩展**：Predis（Composer 包）
    * **Laravel Sail**：默认已包含 PhpRedis
  </Accordion>

  <Accordion title="连接配置要点">
    * 多个 Redis 连接在 `config/database.php` 中按用途分开（`default` / `cache` 等）
    * 集群环境使用 `clusters` 键
    * 生产环境建议开启 TLS 并配置认证信息
  </Accordion>

  <Accordion title="不同操作的使用场景">
    | 操作                          | 用途                |
    | --------------------------- | ----------------- |
    | Facade 方法                   | 常规 Redis 命令       |
    | `transaction()`             | 多命令原子执行（不能读取值）    |
    | `eval()`                    | Lua 脚本（支持读取的原子操作） |
    | `pipeline()`                | 大量命令的快速发送（非原子）    |
    | `subscribe()` / `publish()` | 频道消息传递（Pub/Sub）   |
  </Accordion>
</AccordionGroup>


## Related topics

- [缓存](/zh/cache.md)
- [Laravel Sail](/zh/sail.md)
- [限流的自定义](/zh/advanced/rate-limiting.md)
- [队列与任务](/zh/queues.md)
- [Laravel Pulse](/zh/pulse.md)
