Laravel + predis + Redis 集群 - 移动/没有连接到 127.0.0.1:6379 [英] Laravel + predis + Redis cluster - MOVED / no connection to 127.0.0.1:6379
问题描述
我有一个带有用于会话的 redis 的 laravel (5.3) 应用程序(使用 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).
我尝试将集群参数更改为 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 缓存集群高级 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' =>['集群' =>'redis']
需要作为default
的兄弟(不是子)添加到配置中,以便告诉 Predis 处理 Azure 提供的服务器端集群.莉>- 如果在服务器端集群中使用身份验证,
'options' =>['集群' =>'redis', '参数' =>['密码' =>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 将为每个连接创建单独的 PredisClient
实例.每个连接都可以单独访问,与其他连接没有任何关系.
If cluster
is set to false
, Laravel will create individual PredisClient
instances for each connection. Each connection can be accessed individually, and will not have any relation to another connection.
如果 cluster
设置为 true
,Laravel 将使用所有定义的连接创建聚合 PredisClient
实例.没有其他配置,这有点假"簇.它使用客户端分片来分配密钥空间,并且可能需要外部监控和维护以确保适当的密钥负载平衡.
If cluster
is set to true
, Laravel will create an aggregate PredisClient
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 =>;值
对.
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 创建一个可以处理多个节点的聚合 PredisClient
实例,并且options
数组下的 cluster
键将告诉该实例它需要处理服务器端集群,而不是客户端集群.
The cluster
key under the redis
config will tell Laravel to create an aggregate PredisClient
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'
兄弟,它定义了一个参数列表,用于新发现的节点.您可以在此处放置身份验证参数以用于新节点.
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)],
],
],
公平警告,这是我刚刚从研究和代码潜水中获得的所有信息.虽然我已经在 Laravel 中使用了 Redis,但我还没有使用过服务器端集群(还没有),所以这仍然可能不起作用.
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 issue 讨论连接到 redis-cluster:
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 PredisClient([$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 文章讨论了 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
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.
用于创建 PredisClient
实例的 Laravel 代码:
https://github.com/laravel/framework/blob/v5.3.28/src/Illuminate/Redis/Database.php#L25-L66
Laravel code for creating PredisClient
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屋!