Laravel + Predis + Redis集群-已移动/未连接到127.0.0.1:6379 [英] Laravel + predis + Redis cluster - MOVED / no connection to 127.0.0.1:6379
问题描述
我有一个laravel(5.3)应用,其中redis用于会话(使用predis).只要我使用单个redis节点(使用 config/database.php 中的默认方法),一切都可以正常工作.虽然我刚开始切换到Redis集群,但50%的时间都出现MOVED错误(基于谷歌搜索,我知道这应该由predis管理,但不是这样).
I have a laravel (5.3) app with redis used for sessions (using predis). Everything works as long as I use a single redis node (using default approach from config/database.php). As soon as I switch to a Redis cluster though I am starting to get MOVED error like 50% of the time (based on googling I understand that this should be managed by predis, but somehow isn't).
我尝试将cluster参数更改为true,但随后出现一个奇怪的错误
I tried changing the cluster parameter to true, but then I get a weird error
No connection could be made because the target machine actively refused it. [tcp://127.0.0.1:6379]
尽管我使用的redis群集已部署在Azure中(并通过.env文件配置),并且在使用单个节点时可以毫无问题地接受参数.
Although the redis cluster that I use is deployed in Azure (and is configured via .env file) and the parameters are accepted without any problem when a single node is used.
配置
这是我拥有的laravel配置(如前所述,它是标准默认设置)
Here is the laravel configuration that I have (as mentioned earlier, it's the standard default)
'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 Cache Cluster Premium P1,2个分片(如
For Redis, I use Azure Redis Cache Cluster Premium P1, 2 shards (as described here).
更新2
到目前为止,我还尝试了以下配置变化:
So far I also tried the following variations of the config:
- 将集群设置为true
- 将集群设置为redis
- 添加默认->将集群设置为redis
- 添加默认->选项设置为array('cluster','redis')
我一直遇到MOVED错误...
All the time I am getting MOVED error...
我的Redis版本是3.2,predis/predis软件包1.1.1
My Redis version is 3.2, predis/predis package 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)], ]
来对新发现的群集节点进行身份验证. 'cluster' => true
should be true to create one aggregate client that handles multiple nodes.'options' => ['cluster' => 'redis']
needs to be added to the configuration as a sibling ofdefault
(not a child) in order to tell Predis to handle the server-side clustering provided by Azure.- if using auth with server-side clustering,
'options' => [ 'cluster' => 'redis', 'parameters' => ['password' => env('REDIS_PASSWORD', null)], ]
will be needed to auth newly discovered cluster nodes.
TL;DR:
在redis配置中,您可以建立到多个Redis实例的多个连接. cluster
选项告诉Laravel如何处理这些多个已定义的连接.
In the redis configuration, you can set up multiple connections to multiple redis instances. The cluster
option tells Laravel how to handle those multiple defined connections.
如果将cluster
设置为false
,Laravel将为每个连接创建单独的\Predis\Client
实例.每个连接都可以单独访问,并且与另一个连接没有任何关系.
If cluster
is set to false
, Laravel will create individual \Predis\Client
instances for each connection. Each connection can be accessed individually, and will not have any relation to another connection.
如果将cluster
设置为true
,Laravel将使用所有定义的连接创建一个聚合的\Predis\Client
实例.在没有其他配置的情况下,这是一种伪"集群.它使用客户端分片来分发密钥空间,并且可能需要外部监视和维护以确保适当的密钥负载平衡.
If cluster
is set to true
, Laravel will create an aggregate \Predis\Client
instance using all the defined connections. With no other configuration, this is kind of a "fake" cluster. It uses client-side sharding to distribute the keyspace and may require external monitoring and maintenance to ensure a proper key load balance.
但是,您遇到的问题是,Azure实现了(大概是)真实的服务器端Redis群集,该群集处理密钥空间的自动分片.在这种情况下,节点相互了解并相互交谈,并且可能会上下波动.这是MOVED
和ASK
响应的来源.
The issue you're running into, however, is that Azure implements (presumably) a real server-side Redis cluster, which handles automatic sharding of the keyspace. In this instance, the nodes know about each other and talk to each other, and may go up and down. This is where MOVED
and ASK
responses come from.
Predis
库可以自动处理这些响应,但是只有在您告诉它需要时才可以.在这种情况下,您需要告诉Predis
客户端它需要处理集群,这是由Laravel通过redis
配置上的options
数组完成的.
The Predis
library can automatically handle these responses, but only when you tell it that it needs to. In this case, you need to tell the Predis
client that it needs to handle clustering, and this is done by Laravel through the options
array on the redis
configuration.
在redis
配置上,options
键应该是您的连接的同级对象(即default
),而不是子级.此外,应将选项指定为key => value
对.
On the redis
configuration, the options
key should be a sibling of your connections (i.e. default
), not a child. Additionally, the options should be specified as key => value
pairs.
因此,您的配置应如下所示:
So, your configuration should look like:
'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
键将告诉该实例它需要处理服务器端群集,而不是客户端群集.
The cluster
key under the redis
config will tell Laravel to create an aggregate Predis\Client
instance that may handle multiple nodes, and the cluster
key under the options
array will tell that instance that it needs to handle server-side clustering, not client-side clustering.
原始连接参数(包括身份验证)未与通过-MOVED
和-ASK
响应发现的新节点的连接共享.因此,您以前从-MOVED
响应中得到的任何错误现在都将转换为NOAUTH
错误.但是,服务器端'cluster'
配置允许'parameters'
同级,该同级定义了与新发现的节点一起使用的参数列表.在这里您可以将auth参数与新节点一起使用.
The original connection parameters (including authentication) are not shared with connections to new nodes discovered via -MOVED
and -ASK
responses. So, any errors you previously got from -MOVED
responses will now just convert to NOAUTH
errors. However, the server-side 'cluster'
configuration allows for a 'parameters'
sibling which defines a list of parameters to use with newly discovered nodes. This is where you can put your auth parameters to use with new nodes.
我相信这看起来像:
'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结合使用,但尚未使用服务器端集群(因此),所以这可能仍然行不通.
Fair warning, this is all information I just got from research and code diving. While I have used Redis with Laravel, I have not used server side clustering (yet), so this still may not work.
我在研究此信息时遇到了一些有用的信息:
Some useful pieces of information I came across while looking into this:
Predis问题讨论如何连接到Redis集群:
https://github.com/nrk/predis/issues/259#issuecomment-117339028
Predis issue discussing connecting to a redis-cluster:
https://github.com/nrk/predis/issues/259#issuecomment-117339028
您似乎没有将Predis配置为使用redis-cluster,而是将其与普通的旧客户端分片逻辑一起使用(这也是默认行为).您应该配置客户端,将选项集群设置为值redis,以使客户端知道它必须与redis-cluster一起使用.快速示例:
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']);
这样做将使客户端可以自动处理来自Redis节点的-MOVED或-ASK响应.
Doing so will make it possible for the client to automatically handle -MOVED or -ASK responses coming from Redis nodes.
MS article discussing clustering on redis cache:
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
您可以使用与连接到未启用群集的缓存时使用的相同的端点,端口和键连接到缓存. Redis在后端管理集群,因此您不必从客户端进行管理.
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 code for creating Predis\Client
instances:
https://github.com/laravel/framework/blob/v5.3.28/src/Illuminate/Redis/Database.php#L25-L66
这篇关于Laravel + Predis + Redis集群-已移动/未连接到127.0.0.1:6379的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!