laravel - Laravel + Predis + Redis集群-已移动/未连接到127.0.0.1 :6379

标签 laravel redis azure-caching

我有一个带有redis的laravel(5.3)应用程序,用于 session (使用predis)。只要我使用单个redis节点(使用config/database.php中的默认方法),一切都可以正常工作。尽管我刚开始切换到Redis集群,但50%的时间都出现MOVED错误(基于谷歌搜索,我知道这应该由predis管理,但不是这样)。

我尝试将cluster参数更改为true,但是随后出现一个奇怪的错误

No connection could be made because the target machine actively refused it. [tcp://127.0.0.1:6379] 

尽管我使用的redis群集已部署在Azure中(并通过.env文件进行配置),并且使用单个节点时,参数可以毫无问题地被接受。

配置

这是我拥有的laravel配置(如前所述,这是标准默认设置)
'redis' => [

        'client' => 'predis',
        'cluster' => false,

        'default' => [
            'host' => env('REDIS_HOST', 'localhost'),
            'password' => env('REDIS_PASSWORD', null),
            'port' => env('REDIS_PORT', 6379),
            'database' => 0,
        ],

    ],

对于Redis,我使用Azure Redis缓存群集高级版P1,2个分片(如here所述)。

更新2

到目前为止,我还尝试了配置的以下变体:
  • 将集群设置为true
  • 将集群设置为redis
  • 添加默认->将集群设置为redis
  • 添加默认->选项设置为array('cluster','redis')

  • 我一直都在出现MOVED错误...

    我的Redis版本是3.2,predis/predis软件包1.1.1

    predis 1.1+的工作配置
    'redis' => [
            'cluster' => true,
    
            'default' => [
                'host' => env('REDIS_HOST', 'localhost'),
                'password' => env('REDIS_PASSWORD', null),
                'port' => env('REDIS_PORT', 6379),
                'database' => 0,
            ] ,
            'options' => [
                'cluster' => 'redis',
                 'parameters' => ['password' => env('REDIS_PASSWORD', null)],
            ],
        ],
    

    非常感谢您的帮助:)

    最佳答案

    TL; DR:

  • 'cluster' => true应该为true,以创建一个处理多个节点的聚合客户端。
  • 'options' => ['cluster' => 'redis']需要作为default的同级项(不是子级)添加到配置中,以便告诉Predis处理Azure提供的服务器端群集。
  • (如果将auth与服务器端群集一起使用),将需要'options' => [ 'cluster' => 'redis', 'parameters' => ['password' => env('REDIS_PASSWORD', null)], ]对新发现的群集节点进行身份验证。

  • 全文
    在redis配置中,您可以设置到多个redis实例的多个连接。 cluster选项告诉Laravel如何处理多个已定义的连接。
    如果cluster设置为false,Laravel将为每个连接创建单独的\Predis\Client实例。每个连接都可以单独访问,并且与另一个连接没有任何关系。
    如果cluster设置为true,Laravel将使用所有定义的连接创建一个聚合的\Predis\Client实例。在没有其他配置的情况下,这是一种“伪”集群。它使用客户端分片来分发 key 空间,并且可能需要外部监视和维护以确保适当的 key 负载平衡。
    但是,您遇到的问题是,Azure实现了(大概是)真实的服务器端Redis群集,该群集处理 key 空间的自动分片。在这种情况下,节点相互了解并相互交谈,并且可能会上下波动。这是MOVEDASK响应来自的地方。Predis库可以自动处理这些响应,但是只有在您告诉它需要时才可以。在这种情况下,您需要告诉Predis客户端它需要处理集群,这是Laravel通过options配置上的redis数组完成的。
    redis配置上,options key 应该是您的连接的同级兄弟(即default),而不是 child 。此外,应将选项指定为key => value对。
    因此,您的配置应如下所示:
    'redis' => [
        'cluster' => true,
    
        'default' => [
            'host' => env('REDIS_HOST', 'localhost'),
            'password' => env('REDIS_PASSWORD', null),
            'port' => env('REDIS_PORT', 6379),
            'database' => 0,
        ],
    
        'options' => [
            'cluster' => 'redis',
        ],
    ],
    
    cluster配置下的redis键将告诉Laravel创建一个可以处理多个节点的聚合Predis\Client实例,而cluster数组下的options键将告诉该实例它需要处理服务器端集群,而不是客户端集群。
    验证码
    原始连接参数(包括身份验证)不会与通过-MOVED-ASK响应发现的新节点的连接共享。因此,您以前从-MOVED响应中得到的任何错误现在都将转换为NOAUTH错误。但是,服务器端'cluster'配置允许'parameters'同级,该同级定义了与新发现的节点一起使用的参数列表。在这里,您可以将auth参数与新节点一起使用。
    我相信这看起来像:
    'redis' => [
        'cluster' => true,
    
        'default' => [
            'host' => env('REDIS_HOST', 'localhost'),
            'password' => env('REDIS_PASSWORD', null),
            'port' => env('REDIS_PORT', 6379),
            'database' => 0,
        ],
    
        'options' => [
            'cluster' => 'redis',
            'parameters' => ['password' => env('REDIS_PASSWORD', null)],
        ],
    ],
    

    公平的警告,这就是我刚刚从研究和代码潜水中获得的所有信息。虽然我将Redis与Laravel结合使用,但尚未使用服务器端集群(因此),因此这可能仍然行不通。
    我在研究时遇到了一些有用的信息:
    Predis讨论连接到Redis集群的问题:
    https://github.com/nrk/predis/issues/259#issuecomment-117339028

    It looks like you did not configure Predis to use redis-cluster but instead you are using it with the plain old client-side sharding logic (which is also the default behaviour). You should configure the client setting the option cluster with the value redis to let the client know it must play along with redis-cluster. Quick example:

    $client = new Predis\Client([$node1, $node2, ...], ['cluster' => 'redis']);

    Doing so will make it possible for the client to automatically handle -MOVED or -ASK responses coming from Redis nodes.


    MS文章讨论Redis缓存上的群集:
    https://docs.microsoft.com/en-us/azure/redis-cache/cache-how-to-premium-clustering#how-do-i-connect-to-my-cache-when-clustering-is-enabled

    You can connect to your cache using the same endpoints, ports, and keys that you use when connecting to a cache that does not have clustering enabled. Redis manages the clustering on the backend so you don't have to manage it from your client.


    用于创建Predis\Client实例的Laravel代码:
    https://github.com/laravel/framework/blob/v5.3.28/src/Illuminate/Redis/Database.php#L25-L66

    关于laravel - Laravel + Predis + Redis集群-已移动/未连接到127.0.0.1 :6379,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41091103/

    相关文章:

    php - 以JSON格式返回验证错误消息-Laravel 6

    laravel - 如何使用多个 slack webhook 进行 Laravel 通知

    apache-spark - Spark-redis:数据帧写入时间太慢

    redis - 如何在 3.0.7 上迁移 redis 集群中的巨大 key ?

    asp.net - 多个实例使用共置缓存但无法访问,需要良好的命名缓存实现

    azure - 增加缓存角色的MaxBufferSize

    php - Laravel Query Builder 的 updateOrInsert 函数有什么特点?

    php - 我是否必须从 Laravel 中每个 Controller 的数据库中返回 header 数据?

    redis - 如何根据我的域中引发的事件在 RedMQ 中设置处理程序

    Azure 缓存 - Microsoft Enterprise Library 5.0 在 Azure 上缓存应用程序 block 如何?