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

zbq4xfa0  于 2022-11-18  发布在  Redis
关注(0)|答案(7)|浏览(186)

我有一个laravel(5.3)的应用程序,使用redis(使用predis)。只要我使用一个redis节点,一切都可以正常工作(使用 config/database.php 中的默认方法)。一旦我切换到Redis集群,虽然我开始得到MOVED错误,大约50%的时间(基于谷歌搜索,我知道这应该由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

到目前为止,我还尝试了以下配置变体:
1.将cluster设置为true
1.将群集设置为redis
1.正在将default -〉cluster集添加到redis
1.将default -〉选项集添加到数组('cluster','redis')
所有的时间我都得到移动错误...
我的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)],
        ],
    ],

非常感谢你们的帮助:)

ufj5ltwl

ufj5ltwl1#

注意
此处指定的信息和配置适用于Laravel 5.3及更低版本。Redis配置结构在Laravel 5.4+中已更改。

TL;DR的名称

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

全文

在redis配置中,你可以设置多个连接到多个redis示例。cluster选项告诉Laravel如何处理这些定义的多个连接。
如果cluster设置为false,Laravel将为每个连接创建单独的\Predis\Client示例。每个连接都可以单独访问,并且与其他连接没有任何关系。
如果cluster设置为true,Laravel将使用所有定义的连接创建一个聚合\Predis\Client示例。如果没有其他配置,这是一种“假”集群。它使用客户端分片来分发密钥空间,可能需要外部监视和维护以确保正确的密钥负载平衡。
然而,你遇到的问题是,Azure实现了(可能是)一个真实的的服务器端Redis集群,它处理密钥空间的自动分片。在这个例子中,节点彼此知道,彼此交谈,可能会上升和下降。这就是MOVEDASK响应的来源。
Predis库可以自动处理这些响应,但只有当您告诉它需要这样做时才可以。在这种情况下,您需要告诉Predis客户端它需要处理集群,这是由Laravel通过redis配置上的options数组完成的。
redis配置中,options键应该是连接的同级(即default),而不是子项。此外,选项应该指定为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',
    ],
],

redis配置下的cluster键将告诉Laravel创建一个可以处理多个节点的聚合Predis\Client示例,而options数组下的cluster键将告诉该示例它需要处理服务器端群集,而不是客户端群集。

验证

原始连接参数(包括验证)不会与通过-MOVED-ASK响应发现的新节点的连接共享。因此,以前从-MOVED响应获得的任何错误现在都将转换为NOAUTH错误。但是,服务器端'cluster'配置允许使用'parameters'同级节点,该同级节点定义了一个参数列表,以便用于新发现的节点。您可以在此放置身份验证参数,以便用于新节点。
我相信这看起来像这样:

'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)],
    ],
],

公平的警告,这是我刚刚从研究和代码潜水中得到的所有信息。虽然我已经在Laravel上使用过Redis,但我还没有使用服务器端集群(还没有),所以这仍然可能不起作用。
我在调查这件事时发现了一些有用的信息:
Predis讨论连接到redis集群的问题:
https://github.com/nrk/predis/issues/259#issuecomment-117339028
看起来你并没有配置Predis使用redis-cluster,而是使用了普通的客户端分片逻辑(这也是默认行为)。你应该配置客户端的cluster选项为redis,让客户端知道它必须沿着redis-cluster。举个例子:
x1米32英寸
这样客户端就可以自动处理来自Redis节点的-MOVED或-ASK响应。
讨论Redis缓存集群的MS文章:
https://learn.microsoft.com/en-us/azure/redis-cache/cache-how-to-premium-clustering#how-do-i-connect-to-my-cache-when-clustering-is-enabled
您可以使用与连接未启用集群的缓存时相同的端点、端口和键来连接缓存。Redis在后端管理集群,因此您不必从客户端进行管理。
用于创建Predis\Client示例的Laravel代码:
https://github.com/laravel/framework/blob/v5.3.28/src/Illuminate/Redis/Database.php#L25-L66

ep6jt1vc

ep6jt1vc2#

相关:Laravel + Redis通过SSL缓存?
我在这里回答:https://stackoverflow.com/a/48876398/663058

相关详情如下:

如果您有集群 * 和 * TLS,则需要以下配置(使用AWS Elasticache进行测试):

'redis' => [
        'client' => 'predis',
        'cluster' => env('REDIS_CLUSTER', false),

        // Note! for single redis nodes, the default is defined here.
        // keeping it here for clusters will actually prevent the cluster config
        // from being used, it'll assume single node only.
        //'default' => [
        //    ...
        //],

        // #pro-tip, you can use the Cluster config even for single instances!
        'clusters' => [
            'default' => [
                [
                    'scheme'   => env('REDIS_SCHEME', 'tcp'),
                    'host'     => env('REDIS_HOST', 'localhost'),
                    'password' => env('REDIS_PASSWORD', null),
                    'port'     => env('REDIS_PORT', 6379),
                    'database' => env('REDIS_DATABASE', 0),
                ],
            ],
            'options' => [ // Clustering specific options
                'cluster' => 'redis', // This tells Redis Client lib to follow redirects (from cluster)
            ]
        ],
        'options' => [
            'parameters' => [ // Parameters provide defaults for the Connection Factory
                'password' => env('REDIS_PASSWORD', null), // Redirects need PW for the other nodes
                'scheme'   => env('REDIS_SCHEME', 'tcp'),  // Redirects also must match scheme
            ],
            'ssl'    => ['verify_peer' => false], // Since we dont have TLS cert to verify
        ]
    ]

解释上述内容:

  • 'client' => 'predis':指定要使用的PHP库Redis驱动程序(predis)。
  • 'cluster' => 'redis':这告诉Predis假设服务器端集群。这只是意味着“跟随重定向”(例如-MOVED响应)。当与集群一起运行时,节点将使用-MOVED响应您必须请求特定键的节点。
  • 如果你没有在Redis集群中启用这个功能,Laravel会抛出-MOVED异常1/n 次,n 是Redis集群中的节点数(它会很幸运地每隔一段时间询问正确的节点)
  • 'clusters' => [...]:指定一个节点列表,但只设置一个“default”并将其指向AWS的“Configuration endpoint”将允许它动态地查找任何/所有其他节点(建议用于Elasticache,因为您不知道节点何时到来或离开)。
  • 'options':对于Laravel,可以在顶层、集群级和节点选项中指定。(它们在传递到Predis之前在Illuminate中组合)
  • 'parameters':这些“覆盖”Predis用于新连接的默认连接设置/假设。由于我们为“默认”连接明确设置了这些设置,因此不会使用这些设置。但对于集群设置,它们是至关重要的。"主“节点可能会发回重定向(-MOVED),除非为passwordscheme设置了参数,否则它将采用默认值,并且到新节点的新连接将失败。
jutyujz0

jutyujz03#

在应用了很多建议之后,我终于找到了使用phpredis而不是Redis的解决方案。使用下面的代码:

'redis' => [

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

],

使用官方文档更好地理解Laravel Redis集群

oknwwptz

oknwwptz4#

对于AWS elasticcache redis集群,上述配置不起作用,但以下配置对我来说是有效的。文档中也提到:https://laravel.com/docs/5.4/redis#configuration

'redis' => [
    'client' => 'predis',
    'options' => [
        'cluster' => 'redis',
    ],
    'clusters' => [
        'default' => [
            [
                'host' => env('REDIS_HOST', 'localhost'),
                'password' => env('REDIS_PASSWORD', null),
                'port' => env('REDIS_PORT', 6379),
                'database' => 0,
            ],
        ],
    ],
],
arknldoa

arknldoa5#

请参阅[ https://laravel.com/docs/5.5/redis ]。
请确保您有正确的库

composer require predis/predis

在config/database.php和config/queue.php中[如果你的队列也使用集群reddis]

'redis' => [

    'client' => 'predis',
    'options' => [
        'cluster' => 'redis',
    ],
    'clusters' => [
        'default' => [
            [
                'host' => env('REDIS_HOST', 'localhost'),
                'password' => env('REDIS_PASSWORD', null),
                'port' => env('REDIS_PORT', 6379),
                'database' => 0,
            ],
        ],
    ],

]
kpbpu008

kpbpu0086#

这对我很有效:

'redis' => [
    'client' => 'predis',
    'cluster' => true,
    'options' => [
        'cluster' => 'redis',
        'parameters' => [
            'host' => env('REDIS_DEFAULT_HOST', '127.0.01'),
            'password' => env('REDIS_PASSWORD', null),
            'port' => env('REDIS_DEFAULT_PORT', 6379),
            'database' => 0,
            ],
        ],
    'clusters' => [
         'default' => [
            'host' => env('REDIS_DEFAULT_HOST', '127.0.01'),
            'password' => env('REDIS_PASSWORD', null),
            'port' => env('REDIS_DEFAULT_PORT', 6379),
            'database' => 0,
        ],
        'jobs' => [
            'host' => env('REDIS_JOBS_HOST', '127.0.01'),
            'password' => env('REDIS_PASSWORD', null),
            'port' => env('REDIS_JOBS_PORT', 6379),
            'database' => 0,
        ],
        'content' => [
            'host' => env('REDIS_CONTENT_HOST', '127.0.01'),
            'password' => env('REDIS_PASSWORD', null),
            'port' => env('REDIS_CONTENT_PORT', 6379),
            'database' => 0,
        ],
        'options' => [
            'cluster' => 'redis'
        ],
    ]
]

要了解我是如何做到这一点的,请参阅我的答案here

bbuxkriu

bbuxkriu7#

这个结果出现在Google的predis+redis-cluster(没有laravel)上。我和我的团队为这个问题纠结了几个小时,所以我把这个答案放在这里,给那些在试图直接连接到Redis集群时发现这个页面出现错误的人:

$redis = new Predis\Client(
   ['tcp://127.0.0.1:6379'],
   ['cluster' => 'redis']
);

相关问题