tcgunel/laravel-redis-sentinel-drivers

Laravel和Lumen的Redis Sentinel集成。

v3.0.0 2023-11-24 12:53 UTC

This package is auto-updated.

Last update: 2024-09-24 14:54:38 UTC


README

monospice/laravel-redis-sentinel-drivers的分支

Laravel Redis Sentinel驱动程序

Build Status Scrutinizer Code Quality Latest Stable Version Total Downloads License

Laravel和Lumen的Redis Sentinel集成。

Redis Sentinel简化了配置Redis服务器以支持主从复制,并提供了高可用性、监控和负载均衡功能。Laravel内置了Redis支持,但我们无法直接灵活地配置Sentinel设置,这限制了Sentinel只能配置一个服务。

例如,如果我们想在Laravel的API中同时使用Redis Sentinel来处理缓存和会话,我们无法像在非Sentinel的单服务器Redis配置中那样为两种类型的数据设置不同的Redis数据库。当需要清除缓存时,这会导致问题,因为Laravel会同时删除存储的会话信息。

此包将Laravel的广播、缓存、会话和队列API的配置包装起来,并允许独立设置Redis服务的选项。它为Laravel Horizon添加了Sentinel支持,并解决了其他兼容性问题。

我们独立于Laravel的标准Redis配置来配置此包,因此可以根据环境需要选择使用Sentinel连接。开发人员可以在本地环境中使用独立的Redis服务器,而生产环境可以运行Redis Sentinel服务器集。

内容

需求

  • PHP 5.4或更高版本
  • Redis 2.8或更高版本(用于Sentinel支持)
  • Predis 1.1或更高版本(用于Sentinel客户端支持)
  • LaravelLumen 5.0或更高版本(4.x不支持所需的Predis版本)

注意: Laravel 5.4引入了使用PhpRedis扩展作为框架Redis客户端的功能。此包目前不支持PhpRedis选项。

此Readme假定您已具备为Redis配置Redis Sentinel以及使用Redis与LaravelLumen的知识。

安装

由于我们使用Laravel,所以当然会通过Composer进行安装!

对于Laravel/Lumen 5.4及以上版本

composer require monospice/laravel-redis-sentinel-drivers

对于Laravel/Lumen 5.3及以下版本

composer require monospice/laravel-redis-sentinel-drivers:^1.0

注意: 根据Laravel发布计划,所有在2017年8月之前发布的Laravel版本都已停止活跃开发和支持。2017年12月之后,此包将不再为5.4之前的Laravel版本提供1.x分支的功能发布。

如果项目尚未使用Laravel的Redis,则此安装还将安装Predis包。

注册服务提供者

Laravel 5.5 引入了包发现功能!Laravel 5.5 及以上版本无需注册服务提供者。

要在 Laravel 5.4 及以下版本中使用驱动,请将包的服务提供者添加到 config/app.php

'providers' => [
    ...
    Monospice\LaravelRedisSentinel\RedisSentinelServiceProvider::class,
    ...
],

在 Lumen 中,请在 bootstrap/app.php 中注册服务提供者

$app->register(Monospice\LaravelRedisSentinel\RedisSentinelServiceProvider::class);

快速入门(TL;DR)

安装包后,在 .env 文件中设置以下内容

CACHE_DRIVER=redis-sentinel
SESSION_DRIVER=redis-sentinel
QUEUE_CONNECTION=redis-sentinel  # Laravel >= 5.7
QUEUE_DRIVER=redis-sentinel      # Laravel <= 5.6
REDIS_DRIVER=redis-sentinel

REDIS_HOST=sentinel1.example.com, sentinel2.example.com, 10.0.0.1, etc.
REDIS_PORT=26379
REDIS_SENTINEL_SERVICE=mymaster  # or your Redis master group name

REDIS_CACHE_DATABASE=1
REDIS_SESSION_DATABASE=2
REDIS_QUEUE_DATABASE=3

以下示例应使用 Redis Sentinel 连接

Redis::get('key');
Cache::get('key');
Session::get('key');
Queue::push(new Job());

此示例通过环境配置了包。它通过将 REDIS_DRIVER 设置为 redis-sentinel 来覆盖 Laravel 的标准 Redis API。有关所有可配置的环境变量,请参阅附录。可选地,启用RedisSentinel 门面

对于那些需要快速开发 Sentinel 服务器集群的开发者,可以尝试包测试文件中包含的 start-cluster.sh 脚本。

配置

根据应用需求,我们可以以三种方式配置此包

混合配置使用了两种或多种这些方法。

从版本 2.2.0 发布以来,该包支持通过环境变量进行简单配置,这些环境变量具有适合许多应用的默认配置结构,这特别减轻了 Lumen 用户在初始 Lumen 安装可能不存在的情况下创建多个配置文件的需求。

该包继续支持通过标准配置文件进行高级配置,而无需对现有项目进行更改。

基于环境的配置

对于适合的应用程序,该包能够从环境配置自身,消除了在许多场景下创建或修改配置文件的需求。该包自动使用环境变量配置 Redis Sentinel 连接以及应用程序的广播、缓存、会话和队列服务。

当应用程序需求超过包的自动配置能力时,开发者仍然可以通过标准 Laravel 配置文件配置包。

通常,我们在开发期间在项目的.env 文件中分配应用程序环境变量。基本应用的配置可能仅需要在此文件中设置以下值

REDIS_HOST=sentinel.example.com
REDIS_PORT=26379
REDIS_SENTINEL_SERVICE=mymaster

这为通过RedisSentinel 门面(或从容器解析 app('redis-sentinel'))访问的包服务设置默认 Redis Sentinel 连接(或像使用 Laravel 的标准 Redis API一样)。要使用此 Sentinel 连接为 Laravel 的广播、缓存、会话或队列服务,也要更改以下值

BROADCAST_DRIVER=redis-sentinel
CACHE_DRIVER=redis-sentinel
SESSION_DRIVER=redis-sentinel
QUEUE_CONNECTION=redis-sentinel  # Laravel >= 5.7
QUEUE_DRIVER=redis-sentinel      # Laravel <= 5.6

特定连接的配置

在许多情况下,我们会为应用的广播、缓存、会话和队列设置不同的连接参数。我们可能为缓存和会话配置不同的 Redis 数据库(以便清除缓存不会清除我们的用户会话信息),而包含应用队列的 Redis 服务器可能位于不同的 Sentinel 服务(主组名)之后。

REDIS_CACHE_DATABASE=1
REDIS_SESSION_DATABASE=2
REDIS_QUEUE_SERVICE=queue-service

指定多个主机

要通过环境变量为连接提供多个主机,请将任何 *_HOST 变量的值设置为以逗号分隔的主机名或 IP 地址字符串

REDIS_HOST=sentinel1.example.com, sentinel2.example.com, ...
REDIS_CACHE_HOST=10.0.0.1, 10.0.0.2, 10.0.0.3
REDIS_QUEUE_HOST=tcp://10.0.0.4:26379, tcp://10.0.0.4:26380, ...

除非我们像所示的那样在主机名后显式包含端口号,否则主机共享连接设置的端口号。

混合应用

之前的示例设置了 REDIS_HOSTREDIS_PORT 变量,Laravel 也会读取这些变量来配置标准的 Redis 连接。这使得开发者可以在开发环境中使用相同的变量,使用单个 Redis 服务器,以及在生产环境中使用一组完整的 Sentinel 服务器。但是,如果一个应用程序包含在相同环境中向 Redis 和 Sentinel 连接发送请求的代码,我们必须分配一个或多个特定的 Sentinel 变量。

REDIS_SENTINEL_HOST=sentinel.example.com
REDIS_SENTINEL_PORT=26379
REDIS_SENTINEL_PASSWORD=secret
REDIS_SENTINEL_DATABASE=0

其他环境配置选项

我们可以将 REDIS_DRIVER 的值更改为 redis-sentinel 以覆盖标准的 Laravel Redis API。

有关此包消耗的所有环境变量的完整列表,请参阅附录。查看该包的内部配置文件[内部配置文件]或基于环境的配置示例[环境配置示例],以更好地了解该包如何使用环境变量。

使用标准配置文件

除了基于环境的配置之外,该包还允许开发人员通过 Laravel 的标准配置文件来配置 Redis Sentinel 集成。此选项适用于需要比包默认环境配置更高级或特定配置的应用程序。

为此配置方法,我们将修改以下配置文件

  • config/database.php - 定义 Redis Sentinel 连接
  • config/broadcasting.php - 定义 Redis Sentinel 广播器
  • config/cache.php - 定义 Redis Sentinel 缓存存储
  • config/session.php - 设置会话的 Redis Sentinel 连接
  • config/queue.php - 定义 Redis Sentinel 队列连接

注意: Lumen 用户可以创建一个包配置文件[使用包配置文件]以避免在上述文件不存在的情况下创建所有文件。

当基于环境的配置满足应用程序的需求时,我们不需要修改任何配置文件。以下部分中展示的代码[混合配置]覆盖了包的自动配置。

Redis Sentinel 连接配置

我们将单独配置 Redis Sentinel 数据库连接,而不是 Laravel 默认的 Redis 数据库连接。这使得我们可以在需要时使用 Laravel 的标准 Redis 功能,例如,如果开发者在本地环境中运行单个 Redis 服务器,而生产环境运行一组完整的 Redis 和 Sentinel 服务器。我们不需要移除 Laravel 默认提供的 'redis' 驱动配置块。

注意: Laravel 将这些配置选项传递给 Predis 客户端库,因此如果需要,我们可以在此处包含高级配置选项。有关更多信息,请参阅 Predis 文档

基本配置

对于使用单个 Sentinel 服务器的基本设置,请将以下块添加到 config/database.php 中的 'redis-sentinel' 数据库驱动程序。

'redis-sentinel' => [

    'default' => [
        [
            'host' => env('REDIS_HOST', 'localhost'),
            'port' => env('REDIS_PORT', 26379),
        ],
    ],

    'options' => [
        'service' => env('REDIS_SENTINEL_SERVICE', 'mymaster'),
        'parameters' => [
            'password' => env('REDIS_PASSWORD', null),
            'database' => 0,
        ],
    ],

],

正如您所看到的,我们的 'default' 连接包括 Sentinel 服务器地址或主机名以及应用程序连接到的端口(通常是 26379)。由于 Sentinel 不直接支持身份验证,我们将在 'parameters' 数组中设置 Redis 服务器的密码,该数组还包括用于连接的 Redis 数据库。'service' 选项声明了在 Sentinel 中配置的 Redis 服务器组的名称。

请注意顶层数组中 'default' 连接的子数组。如果我们选择向此配置添加其他 Sentinel 服务器,我们将像以下部分中看到的那样,将每个主机的定义包装在另一个数组中。

当然,务必将上面示例中的环境配置变量添加到 .env 文件中。

高级配置

上面的配置块几乎可以完全替代 Laravel 内置的 'redis' 连接配置,我们可以使用它来配置应用程序以使用 Sentinel 而不使用此包。然而,由于 Laravel 解析其 Redis 配置方式存在限制,我们不能配置 Laravel 的标准 Redis 连接进行比基本 Sentinel 设置更复杂的配置。单个 Sentinel 服务器或连接通常不足以用于高可用性或复杂的应用程序。请参阅附录中的 示例 以获取更稳健的配置说明

其他 Sentinel 连接选项

Predis 客户端支持一些额外的配置选项,这些选项确定它如何处理与 Sentinel 服务器的连接。我们可以将这些选项添加到全局 'options' 数组中,用于所有 Sentinel 连接,或者添加到单个连接的本地 'options' 数组中。以下显示默认值

'options' => [
    ...

    // The default amount of time (in seconds) the client waits before
    // determining that a connection attempt to a Sentinel server failed.
    'sentinel_timeout' => 0.100,

    // The default number of attempts to retry a command when the client fails
    // to connect to a Redis or Sentinel server. A value of 0 instructs the
    // client to throw an exception after the first failed attempt, while a
    // value of -1 causes the client to continue to retry commands indefinitely.
    'retry_limit' => 20,

    // The default amount of time (in milliseconds) that the client waits before
    // attempting to contact another Sentinel server or retry a command if the
    // previous server did not respond.
    'retry_wait' => 1000,

    // Instructs the client to query the first reachable Sentinel server for an
    // updated set of Sentinels each time the client needs to establish a
    // connection with a Redis master or replica.
    'update_sentinels' => false,
],

广播、缓存、会话和队列驱动程序

配置 Sentinel 数据库连接后,我们可以指示 Laravel 使用这些连接来为应用程序的其他 Redis 启用服务。请记住,我们不需要为所有这些服务设置 Sentinel 连接。如果我们希望,可以选择标准 Redis 连接一个,Sentinel 连接另一个,但我们可能希望利用 Sentinel 来处理所有 Redis 连接,如果它可用的话。

注意:我们可以完全省略(或删除)以下配置块,并且包将为我们配置这些服务。如果我们像上面那样创建了自定义 Sentinel 连接,我们可能需要 声明这些连接名称

广播

将以下连接定义添加到 config/broadcasting.php 中的 'connections' 数组

'connections' => [
    ...
    'redis-sentinel' => [
        'driver' => 'redis-sentinel',
        'connection' => 'default',
    ],
],

...并将 BROADCAST_DRIVER 环境变量更改为 redis-sentinel.env 中。

如果应用程序在 'redis-sentinel' 数据库配置中包含特定的事件广播连接,用其名称替换 'default'

缓存

将以下存储定义添加到 config/cache.php 中的 'stores' 数组

'stores' => [
    ...
    'redis-sentinel' => [
        'driver' => 'redis-sentinel',
        'connection' => 'default',
    ],
],

...并将 CACHE_DRIVER 环境变量更改为 redis-sentinel.env 中。

如果应用程序在 'redis-sentinel' 数据库配置中包含特定的缓存连接,用其名称替换 'default'

会话

SESSION_DRIVER 环境变量更改为 redis-sentinel.env 中。然后,在 config/session.php 中,将 'connection' 指令设置为 'default',或 'redis-sentinel' 数据库配置中用于存储会话的特定连接的名称。

队列

将以下连接定义添加到 config/queue.php 中的 'connections' 数组

'connections' => [
    ...
    'redis-sentinel' => [
        'driver' => 'redis-sentinel',
        'connection' => 'default',
        'queue' => 'default',
        'retry_after' => 90, // Laravel >= 5.4.30
        'expire' => 90,      // Laravel < 5.4.30
    ],
],

...并将 QUEUE_CONNECTION(Laravel 5.7+)或 QUEUE_DRIVER(Laravel <= 5.6)环境变量更改为 redis-sentinel.env 中。

如果应用程序在队列的 'redis-sentinel' 数据库配置中包含特定的连接,请将 'connection' => 'default' 替换为其名称。

使用包配置文件

Lumen 项目默认不包含配置文件。相反,根据惯例,Lumen 从环境中读取配置信息。如果我们希望通过配置文件来配置此包,如上一节中所述,而不是使用基于环境的配置,我们可以添加一个单个的包配置文件:config/redis-sentinel.php。这可以减少在 Lumen 中创建多个标准配置文件的需要。

包配置文件包含在运行时合并回主配置位置的元素。例如,当自定义的 redis-sentinel.php 文件包含

return [
    'database' =>
        'redis-sentinel' => [ /* ...Redis Sentinel connections... */ ]
    ]
];

...该包将在应用程序启动时设置 database.redis-sentinel 配置值,从 redis-sentinel.database.redis-sentinel 的值,除非键已存在

我们可以通过将其复制到项目的 config/ 目录并更改所需的值来自定义包的内部配置文件 Lumen 用户如果该目录不存在,则需要创建它。

自定义包配置文件只需要包含开发者希望自定义的顶级元素:在上述代码中,自定义配置文件仅覆盖了包的 Redis Sentinel 连接的默认配置,因此包仍会自动使用环境变量配置广播、缓存、会话和队列服务。

混合配置

尽管在大多数情况下不需要,但开发者可以组合使用此包提供的两种或多种配置方法。例如,一个应用程序可能包含一个定义 Redis Sentinel 连接的标准配置文件,但依赖包的自动基于环境的配置来设置 Sentinel 的缓存、会话、队列和广播服务。

包按以下优先级使用配置数据

  1. 标准的 Laravel 配置文件
  2. 自定义包配置文件
  3. 自动基于环境的配置

这意味着标准配置文件中的特定于包的值覆盖自定义包配置文件中的值,而后者又通过环境变量覆盖包的默认自动配置。换句话说,自定义包配置文件继承了未明确声明的包默认配置的值,而主应用程序配置从这两个值中接收未在标准配置文件中提供的值。

覆盖标准Redis API

此包为 Laravel 的缓存、会话和队列 API 添加了 Redis Sentinel 驱动程序,并且开发者可以选择使用 Sentinel 连接利用其中哪一个。然而,Laravel 还提供了API,通过 Redis 门面或通过我们可以通过应用程序容器解析的 Redis 连接管理器(app('redis')、依赖注入等)直接与 Redis 交互。

安装此软件包后,不会强制对所有Redis请求使用Sentinel。事实上,我们可以选择为某些功能使用Sentinel连接,同时继续使用Laravel的标准Redis连接。默认情况下,此软件包不会替换Laravel内置的Redis API。

例如,我们可能决定为应用程序的缓存和会话使用Sentinel连接,但直接使用Laravel的标准Redis连接与单个Redis服务器进行交互。

尽管如此,此软件包提供选项可以覆盖Laravel的Redis API,以便任何Redis命令都使用由'redis-sentinel'数据库驱动程序定义的Sentinel连接配置。

要使用此功能,将以下配置指令添加到config/database.php'redis'连接定义的根目录(如果未使用基于环境的配置)

'redis' => [
    ...
    'driver' => env('REDIS_DRIVER', 'default'),
    ...
],

...并在.env中添加环境变量REDIS_DRIVER,其值为redis-sentinel

启用后,通过Redis外观或redis服务(如app('redis'))执行的Redis命令将使用Sentinel连接。

这使得开发者在本地环境中使用独立的Redis服务器,并在生产环境中切换到完整的Sentinel服务器组变得更容易。

注意:在使用Laravel Horizon时,此更改将导致Horizon通过Sentinel连接运行。

执行Redis命令(RedisSentinel Facade)

如果我们需要将Redis命令直接发送到Sentinel服务器后面的Redis实例,例如我们可以通过Redis外观完成,但不想像上面那样覆盖Laravel的Redis API,我们可以使用此软件包提供的RedisSentinel外观或从应用程序容器解析redis-sentinel服务

// Uses the 'default' connection defined in the 'redis-sentinel' config block:
RedisSentinel::get('some-key');
app('redis-sentinel')->get('some-key');

// Uses the 'default' connection defined in the standard 'redis' config block:
Redis::get('some-key');
app('redis')->get('some-key');

这为那些可能需要在同一环境中连接到标准Redis服务器和Sentinel集群的不常见用例提供支持。尽可能按照上一节中描述的方法,在整个应用程序中统一连接到Sentinel,以解耦代码和Redis实现。

在Laravel 5.5+中,外观未自动别名,以确保与PhpRedis扩展的向后兼容性。要在Laravel中启用外观,请将以下别名添加到config/app.php中的'aliases'数组。

'aliases' => [
    ...
    'RedisSentinel' => Monospice\LaravelRedisSentinel\RedisSentinel::class,
    ...
],

在Lumen中,请将别名添加到bootstrap/app.php

class_alias('Monospice\LaravelRedisSentinel\RedisSentinel', 'RedisSentinel');

依赖注入

对于那些更喜欢将Redis Sentinel管理器声明为类的依赖项而不是使用外观的人,我们可以为容器构建对象时容器将解析的接口进行类型提示

use Monospice\LaravelRedisSentinel\Contracts\Factory as RedisSentinel;
...
public function __construct(RedisSentinel $sentinel)
{
    $sentinel->get('some-key');
}

上面的代码明确请求软件包的Sentinel服务的实例。如果我们覆盖Redis API,我们可以使用标准的Redis合约,应用程序将根据配置注入适当的服务

use Illuminate\Contracts\Redis\Factory as Redis;
...
public function __construct(Redis $redis)
{
    // Either a Sentinel connection or a standard Redis connection depending on
    // the value of REDIS_DRIVER or config('database.redis.driver'):
    $redis->get('some-key');
}

其他Sentinel注意事项

以下部分描述了在使用Sentinel连接时需要注意的一些特征。

读写操作

为了在可用资源之间分配负载,客户端在初始化连接时尝试在Redis从服务器上执行读取操作。写入数据的命令始终在主服务器上执行。

事务

事务中的所有命令,即使是只读命令,都在主Redis服务器上执行。当这样做有意义时,避免在事务中调用读取命令以提高负载均衡。

如果由于连接失败而使事务中断,软件包将尝试重新连接并重试事务,直到耗尽配置的允许尝试次数(retry_limit),或者直到整个事务成功。

重要:Predis提供了通过调用不带参数的transaction()获取的专门的多/执行抽象。此API受Sentinel连接故障处理的保护。为了高可用性,请通过传递闭包到transaction()来使用Laravel API。

发布/订阅

在PUB/SUB消息传递中,客户端将消息发布到主服务器。在订阅时,包首先尝试连接到从服务器,然后再回退到主服务器。类似于读取操作,这有助于将负载从主服务器分散出去,因为发布到主服务器的消息会传播到每个从服务器。

对于长时间运行的订阅者应用,需要扩展连接超时或通过将 read_write_timeout 设置为 0 来禁用它。此外,还需要扩展或禁用应用订阅的Redis服务器上的 timeout 配置指令。

当订阅者连接失败时,包将尝试连接到另一个服务器并继续监听消息。对于长时间运行的订阅者连接,可能需要将 retry_limit 的值设置为 -1,以便客户端无限期地重试。请注意,在重新建立连接期间,订阅者可能会错过已发布到通道的消息。

注意: Predis提供了一个PUB/SUB消费者,我们可以通过不带参数调用 pubSubLoop() 来获取。此API 没有 通过Sentinel连接故障处理进行保护。对于高可用性,请使用通过传递闭包给 subscribe()psubscribe() 的Laravel API。

Laravel Horizon

本包的2.4.0版本及以上支持在兼容的应用程序(Laravel 5.5+)中使用与Laravel Horizon队列管理工具兼容的Sentinel连接。

安装Horizon后,我们需要更新 config/horizon.php 中的某些配置设置。

如果需要,将 'use' => 'default' 更改为用于Horizon后端的Sentinel连接名称,该名称在 config/database.php 中配置。

注意: config/database.php 中的标准 'redis' 连接数组必须包含一个与 'use' 指令中指定的Sentinel连接具有相同键的元素。否则,Horizon会引发异常。目前,Horizon不提供让此包处理这种行为的方法,但一个(正在进行中的)pull request可能会在将来消除这个要求。此元素可以包含任何值(但一个匹配的Redis连接配置似乎最合适)。

通过向顶级数组添加以下元素来更改Horizon内部元数据的后端驱动程序

'driver' => env('HORIZON_DRIVER', 'redis');

...并在 .env 中将 redis-sentinel 赋值给 HORIZON_DRIVER

然后,为任何Sentinel队列添加 'waits' 数组中的条目

'waits' => [
    ...
    'redis-sentinel:default' => 60,
],

接下来,在 'environments' 块中更改应使用Sentinel连接的每个队列工作者的连接驱动程序为 redis-sentinel

...
'supervisor-1' => [
    'connection' => 'redis-sentinel',
    ...
],
...

现在,Horizon将使用应用程序的Redis Sentinel连接来监控和处理我们的队列。

注意: 如果我们已经配置了包来覆盖Laravel的标准Redis API(例如,通过将 REDIS_DRIVER 设置为 redis-sentinel),则不需要将 HORIZON_DRIVER 更改为 'redis-sentinel'。该包已经通过Sentinel连接路由所有Redis操作。

测试

本包包括一个PHPUnit测试套件,包括对包的类进行单元测试,以及用于Sentinel特定功能兼容性修复的集成测试套件。这些测试不验证每个Redis命令,因为Predis和Laravel都包含完整的测试套件,并且因为包代码只是封装了这些库。

$ phpunit --testsuite unit
$ phpunit --testsuite integration

单元测试不需要实时的Redis服务器。阅读下一节以获取集成测试环境建议。

注意:Composer在正常安装时不会下载此包的测试文件。我们需要直接克隆包仓库或者使用--prefer-source选项进行安装。

集成测试

此包的集成测试套件验证了Sentinel和Redis特定功能对真实服务器的支持。这些测试至少需要一个监控Redis主服务器的Sentinel服务器。此外,至少有一个从服务器应该与主服务器同步,以实现最佳测试覆盖率。开发者可以提供自己的服务器或使用以下描述的包工具启动环境。

要自定义集成测试使用的Sentinel连接设置,请将phpunit.xml.dist复制到phpunit.xml,并更改<php>...</php>块中定义的常量。

我们可以运行项目根目录提供的start-cluster.sh脚本,启动Redis和Sentinel服务器以创建测试环境。请阅读脚本的帮助页面以获取使用信息。

$ ./start-cluster.sh help

Docker用户可能希望使用此脚本在容器中启动测试服务器

$ docker run --name redis-sentinel \
    -v "$(pwd):/project" \
    -w /project \
    -u "$(id -u):$(id -g)" \
    -e BIND_ADDRESS=0.0.0.0 \
    -e SENTINEL_PORTS='26379-26381' \
    -e REDIS_GROUP_1='service1 6379-6381' \
    -e REDIS_GROUP_2='service2 6382-6384' \
    -e LOGGING=yes \
    -p 6379-6384:6379-6384 \
    -p 26379-26381:26379-26381 \
    --entrypoint start-cluster.sh \
    redis:alpine

该包提供了一个具有相同测试运行选项的Compose文件

$ export CONTAINER_USER_ID="$(id -u):$(id -g)"
$ docker-compose up -d cluster
$ docker-compose run --rm tests [--testsuite ...]

开发者也可以通过将docker-compose.yml复制到docker-compose.override.yml来自定义Compose文件。

许可

MIT许可证(MIT)。请参阅LICENSE文件以获取更多信息。

附录:环境变量

当使用默认的基于环境的配置时,此包会消耗以下环境变量。开发者只需要为适用于其特定应用程序和Redis设置的变量提供值。在大多数情况下,默认值就足够了。

REDIS_{HOST,PORT,PASSWORD,DATABASE}

默认情况下用于所有Sentinel连接的基本连接参数。

为了简化环境配置,此包尝试读取指定多个Sentinel连接共享值的REDIS_*REDIS_SENTINEL_*环境变量。如果应用程序不同时通过Redis Sentinel和标准Redis连接执行命令,则此功能允许开发者在开发(使用单个Redis服务器)和生产(使用完整的Sentinel服务器集)中使用相同的环境变量名称。

  • REDIS_HOST - 一个或多个主机名或IP地址。如果未设置,默认为localhost
  • REDIS_PORT - Sentinel服务器监听的端口。如果未设置,默认为Sentinel连接的26379
  • REDIS_PASSWORD - 如果有的话,用于通过Sentinel(Sentinels本身不支持密码认证)认证Redis服务器的密码。
  • REDIS_DATABASE - 发送命令到Sentinel后面的Redis服务器时选择的数据库编号(在正常Redis配置中为015)。默认为0

REDIS_SENTINEL_{HOST,PORT,PASSWORD,DATABASE}

当应用程序同时使用标准Redis和Redis Sentinel连接时,请设置这些变量而不是上面的变量。

  • REDIS_SENTINEL_HOST - 查看REDIS_HOST
  • REDIS_SENTINEL_PORT - 查看REDIS_PORT
  • REDIS_SENTINEL_PASSWORD - 查看REDIS_PASSWORD
  • REDIS_SENTINEL_DATABASE - 查看REDIS_DATABASE

REDIS_SENTINEL_SERVICE

Redis主节点组名称(在Sentinel服务器配置文件中指定),用于标识所有Sentinel连接使用的默认Sentinel服务。默认值为mymaster

REDIS_CACHE_SERVICEREDIS_SESSION_SERVICEREDIS_QUEUE_SERVICE设置为覆盖特定服务的连接值。

REDIS_SENTINEL_{TIMEOUT,RETRY_LIMIT,RETRY_WAIT,DISCOVERY}

Predis客户端支持一些额外的配置选项,用于确定它如何处理与Sentinel服务器的连接。

  • REDIS_SENTINEL_TIMEOUT - 客户端等待多长时间(以秒为单位)来判定尝试连接Sentinel服务器失败。默认值为0.100
  • REDIS_SENTINEL_RETRY_LIMIT - 客户端尝试联系Sentinel服务器之前,在确定无法联系到法定多数的Sentinel服务器之前的尝试次数。值为0指示客户端在第一次失败尝试后抛出异常,而值为-1则导致客户端无限期地继续重试连接。默认值为20
  • REDIS_SENTINEL_RETRY_WAIT - 客户端在尝试联系另一个Sentinel服务器之前等待多长时间(以毫秒为单位),如果之前的服务器没有响应。默认值为1000
  • REDIS_SENTINEL_DISCOVERY - 指示客户端在需要与Redis主服务器或从服务器建立连接时,每次查询第一个可到达的Sentinel服务器以获取更新的Sentinel集合。默认值为false

REDIS_DRIVER

将此变量的值设置为redis-sentinel覆盖Laravel的标准Redis API

BROADCAST_DRIVERCACHE_DRIVERSESSION_DRIVERQUEUE_CONNECTION

Laravel使用这些值来选择应用程序广播、缓存、会话和队列服务的后端。将值设置为redis-sentinel以使应用程序使用Sentinel连接为每个应使用Sentinel连接的服务。

注意: Laravel 5.7将默认配置文件中的QUEUE_DRIVER重命名为QUEUE_CONNECTION

REDIS_{BROADCAST,CACHE,SESSION,QUEUE}_{HOST,PORT,PASSWORD,DATABASE,SERVICE}

这些变量配置了服务特定的连接参数,当它们与广播、缓存、会话和队列连接的默认Sentinel连接参数不同时。例如

  • REDIS_BROADCAST_HOST - 覆盖默认广播连接的REDIS_HOSTREDIS_SENTINEL_HOST
  • REDIS_CACHE_PORT - 覆盖默认缓存连接的REDIS_PORTREDIS_SENTINEL_PORT
  • REDIS_SESSION_PASSWORD - 覆盖默认会话连接的REDIS_PASSWORDREDIS_SENTINEL_PASSWORD
  • REDIS_QUEUE_DATABASE - 覆盖默认队列连接的REDIS_DATABASEREDIS_SENTINEL_DATABASE
  • REDIS_QUEUE_SERVICE - 覆盖默认队列连接的REDIS_SENTINEL_SERVICE

BROADCAST_REDIS_CONNECTIONBROADCAST_REDIS_SENTINEL_CONNECTION

BROADCAST_DRIVER等于redis-sentinel时,选择用于应用程序广播的Sentinel连接名称。如果未设置,默认为包的内部、自动配置的广播连接。

CACHE_REDIS_CONNECTIONCACHE_REDIS_SENTINEL_CONNECTION

CACHE_DRIVER等于redis-sentinel时,选择用于应用程序缓存的Sentinel连接名称。如果未设置,默认为包的内部、自动配置的缓存连接。

QUEUE_REDIS_CONNECTIONQUEUE_REDIS_SENTINEL_CONNECTION

QUEUE_CONNECTION(Laravel 5.7+)或QUEUE_DRIVER(Laravel <= 5.6)等于redis-sentinel时,选择用于应用程序队列的Sentinel连接名称。如果未设置,默认为包的内部、自动配置的队列连接。

SESSION_CONNECTION

SESSION_DRIVER 等于 redis-sentinel 时,用于存储应用程序会话的 Sentinel 连接名称。如果未设置,则默认为包内部自动配置的 session 连接,除非应用程序配置已包含 session.connection 的值。

REDIS_SENTINEL_AUTO_BOOT

设置为 true 时,此标志指示包在注册服务后立即启动包,而无需等待应用程序启动阶段。这为使用其他服务提供商中的 Sentinel 连接的应用程序提供了立即初始化包的方法。

附录:配置示例

基于环境的配置示例

针对基于环境的配置的补充示例。

开发与生产

此示例展示了在开发环境中运行单个 Redis 服务器而在生产中运行一组完整的 Sentinel 服务器时,我们如何更改环境变量之间的值。

# Development:                    # Production:

CACHE_DRIVER=redis                CACHE_DRIVER=redis-sentinel
SESSION_DRIVER=redis              SESSION_DRIVER=redis-sentinel
QUEUE_CONNECTION=redis            QUEUE_CONNECTION=redis-sentinel

REDIS_HOST=localhost              REDIS_HOST=sentinel1, sentinel2, sentinel3
REDIS_PORT=6379                   REDIS_PORT=26379
REDIS_SENTINEL_SERVICE=null       REDIS_SENTINEL_SERVICE=mymaster

在可能的情况下,别忘了在生产环境中运行 artisan config:cache 命令。这可以显著提高应用程序和该包的配置加载时间。

最佳实践建议我们避免在生产环境中使用开发 .env 文件。考虑使用其他方法来设置环境变量

"phpdotenv 是为开发环境制作的,通常不应在生产环境中使用。在生产中,实际的环境变量应该设置得使在每次请求中加载 .env 文件没有开销。这可以通过使用 Vagrant、chef 或 Puppet 等工具的自动化部署流程来实现,或者可以通过云主机手动设置..."

配置文件示例

这些示例演示了如何设置 Laravel 的标准配置文件以配置更高级的设置。有关使用配置文件的介绍,请参阅配置文件文档

多 Sentinel 连接配置

在真正的高可用 Redis 设置中,我们将在一个投票中运行多个 Sentinel 服务器。这为在 Sentinel 服务器中的一个或多个服务器变得无响应的故障事件中增加了冗余。我们可以在 config/database.php 中的 'default' 连接中添加多个 Sentinel 服务器定义。

...
'redis-sentinel' => [

    'default' => [
        [
            'host' => 'sentinel1.example.com',
            'port' => 26379,
        ],
        [
            'host' => 'sentinel2.example.com',
            'port' => 26379,
        ],
        [
            'host' => 'sentinel3.example.com'
            'port' => 26379,
        ],
    ],

    'options' => [
        'service' => env('REDIS_SENTINEL_SERVICE', 'mymaster'),
        'parameters' => [
            'password' => env('REDIS_PASSWORD', null),
            'database' => 0,
        ],
    ],

],

使用此配置,我们声明了三个可以处理我们的 Redis 服务请求的 Sentinel 服务器,mymaster(主组名,如 Sentinel 服务器配置文件中指定)。如果其中一个 Sentinel 服务器失败,Predis 客户端将选择不同的 Sentinel 服务器来发送请求。

通常,在集群环境中,我们不想像上面那样将每个服务器硬编码到我们的配置中。我们可能会安装某种负载均衡或服务发现,通过聚合主机名(如 sentinels.example.com)将请求路由到 Sentinel 服务器,以实现灵活部署和任意扩展。

多服务连接配置

如前所述,我们可能想要将 Laravel 为我们的每个服务使用的 Redis 连接分开。例如,我们可能为缓存和会话存储在 Redis 服务器上使用不同的数据库。在此示例中,我们可能还希望在由 Sentinel 管理的另一组不同的 Redis 服务器上为类似“消息源”之类的服务创建数据库。为此设置,我们将配置多个 'redis-sentinel' 连接。

...
'redis-sentinel' => [

    'cache' => [
        [
            'host' => env('REDIS_HOST', 'localhost'),
            'port' => env('REDIS_PORT', 26379),
        ],
        'options' => [
            'service' => env('REDIS_SENTINEL_SERVICE', 'mymaster'),
            'parameters' => [
                'password' => env('REDIS_PASSWORD', null),
                'database' => 0,
            ],
        ],
    ],

    'session' => [
        [
            'host' => env('REDIS_HOST', 'localhost'),
            'port' => env('REDIS_PORT', 26379),
        ],
        'options' => [
            'service' => env('REDIS_SENTINEL_SERVICE', 'mymaster'),
            'parameters' => [
                'password' => env('REDIS_PASSWORD', null),
                'database' => 1,
            ],
        ],
    ],

    'feed' => [
        [
            'host' => env('REDIS_HOST', 'localhost'),
            'port' => env('REDIS_PORT', 26379),
        ],
        'options' => [
            'service' => env('REDIS_SENTINEL_FEED_SERVICE', 'feed-service'),
            'parameters' => [
                'password' => env('REDIS_PASSWORD', null),
                'database' => 0,
            ],
        ],
    ],

],

请注意,我们已删除全局 'options' 数组并为每个连接创建了一个本地 'options' 数组。在此示例设置中,我们在一个 Redis 服务器集上存储应用程序缓存和会话,在另一个集上存储消息源数据。在第一个连接块中,我们将存储缓存数据的 Redis 数据库设置为 0,将存储会话数据的数据库设置为 1,这样我们就可以清除应用程序缓存而不删除用户会话。

此示例配置包含用于存储数据流的第二组Redis服务器。示例Sentinel服务器包含第一个组的服务名称配置mymaster,以及第二个组的服务名称配置feed-service。本地连接选项允许我们指定连接请求哪个服务(Redis主节点组名称)。特别是,我们将'feed'连接的服务名称设置为'feed-service'

有关Sentinel服务配置的更多信息,请参阅Redis Sentinel文档