Laravel + predis + Redis 集群 - 移动 / 没有连接到 127.0.0.1:6379
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/41091103/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Laravel + predis + Redis cluster - MOVED / no connection to 127.0.0.1:6379
提问by Lech Migdal
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).
我有一个带有用于会话的 redis 的 laravel (5.3) 应用程序(使用 predis)。只要我使用单个 redis 节点(使用来自config/database.php 的默认方法),一切都可以正常工作。一旦我切换到 Redis 集群,尽管我开始有 50% 的时间出现 MOVED 错误(基于谷歌搜索,我知道这应该由 predis 管理,但不知何故不是)。
I tried changing the cluster parameter to true, but then I get a weird error
我尝试将集群参数更改为 true,但随后出现了一个奇怪的错误
No connection could be made because the target machine actively refused it. [tcp://127.0.0.1:6379]
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.
虽然我使用的redis集群部署在Azure中(并且通过.env文件配置)并且在使用单个节点时参数被接受没有任何问题。
Configuration
配置
Here is the laravel configuration that I have (as mentioned earlier, it's the standard default)
这是我的 Laravel 配置(如前所述,它是标准默认值)
'redis' => [
'client' => 'predis',
'cluster' => false,
'default' => [
'host' => env('REDIS_HOST', 'localhost'),
'password' => env('REDIS_PASSWORD', null),
'port' => env('REDIS_PORT', 6379),
'database' => 0,
],
],
For Redis, I use Azure Redis Cache Cluster Premium P1, 2 shards (as described here).
对于Redis的,我使用的Redis天青缓存集群高级P1,2个碎片(如所描述的在这里)。
UPDATE 2
更新 2
So far I also tried the following variations of the config:
到目前为止,我还尝试了以下配置变体:
- Setting cluster to true
- Setting cluster to redis
- Adding default -> cluster set to redis
- Adding default -> options set to array('cluster', 'redis')
- 将集群设置为 true
- 将集群设置为redis
- 添加默认 -> 集群设置为 redis
- 添加默认 -> 选项设置为 array('cluster', 'redis')
All the time I am getting MOVED error...
我一直收到 MOVED 错误...
My Redis version is 3.2, predis/predis package 1.1.1
我的Redis版本是3.2,predis/predis包1.1.1
Working config for predis 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)],
],
],
Big thank you for all the help :)
非常感谢您的所有帮助:)
回答by patricus
TL;DR:
特尔;博士:
'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.
'cluster' => true
创建一个处理多个节点的聚合客户端应该是正确的。'options' => ['cluster' => 'redis']
需要作为兄弟default
(不是子)添加到配置中,以便告诉 Predis 处理 Azure 提供的服务器端集群。- 如果将身份验证与服务器端集群一起使用,
'options' => [ 'cluster' => 'redis', 'parameters' => ['password' => env('REDIS_PASSWORD', null)], ]
则需要对新发现的集群节点进行身份验证。
Full Text
全文
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.
在 redis 配置中,可以设置多个连接到多个 redis 实例。该cluster
选项告诉 Laravel 如何处理这些多个定义的连接。
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
设置为false
,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.
如果cluster
设置为true
,Laravel 将\Predis\Client
使用所有定义的连接创建一个聚合实例。没有其他配置,这是一种“假”集群。它使用客户端分片来分配密钥空间,并且可能需要外部监控和维护以确保适当的密钥负载平衡。
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.
但是,您遇到的问题是 Azure 实现(大概)一个真正的服务器端 Redis 集群,它处理密钥空间的自动分片。在这种情况下,节点相互了解并相互交谈,并且可以上下移动。这是MOVED
和ASK
反应从何而来。
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.
该Predis
库可以自动处理这些反应,但只有当你告诉它,它需要。在这种情况下,你需要告诉Predis
客户端它需要处理集群,这是由 Laravel 通过配置options
上的数组来完成的redis
。
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.
在redis
配置上,options
键应该是您的连接的兄弟(即default
),而不是孩子。此外,选项应key => value
成对指定。
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',
],
],
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.
该cluster
下键redis
配置会告诉Laravel来创建聚合Predis\Client
可以处理多个节点的实例,而cluster
下键options
阵列会告诉实例它需要处理服务器端集群,而不是客户端集群。
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.
原始连接参数(包括身份验证)不与通过-MOVED
和-ASK
响应发现的新节点的连接共享。因此,您之前从-MOVED
响应中得到的任何错误现在都将转换为NOAUTH
错误。但是,服务器端'cluster'
配置允许'parameters'
定义用于新发现的节点的参数列表的同级。您可以在此处放置身份验证参数以用于新节点。
I believe this will look something 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',
'parameters' => ['password' => env('REDIS_PASSWORD', null)],
],
],
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.
公平警告,这是我刚刚从研究和代码潜水中获得的所有信息。虽然我已经在 Laravel 中使用了 Redis,但我还没有使用过服务器端集群(还没有),所以这仍然可能不起作用。
Some useful pieces of information I came across while looking into this:
我在研究这个时遇到了一些有用的信息:
Predis issue discussing connecting to a redis-cluster:
https://github.com/nrk/predis/issues/259#issuecomment-117339028
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.
看起来您没有将 Predis 配置为使用 redis-cluster,而是将它与普通的旧客户端分片逻辑一起使用(这也是默认行为)。您应该使用值 redis 配置客户端设置选项集群,让客户端知道它必须与 redis-cluster 一起玩。快速示例:
$client = new Predis\Client([$node1, $node2, ...], ['cluster' => 'redis']);
这样做将使客户端可以自动处理来自 Redis 节点的 -MOVED 或 -ASK 响应。
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 缓存集群的 MS 文章:https:
//docs.microsoft.com/en-us/azure/redis-cache/cache-how-to-premium-clustering#how-do-i-connect-to-my-启用集群时缓存
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.
您可以使用连接到未启用集群的缓存时使用的相同端点、端口和密钥连接到缓存。Redis 在后端管理集群,因此您不必从客户端管理它。
Laravel code for creating Predis\Client
instances:
https://github.com/laravel/framework/blob/v5.3.28/src/Illuminate/Redis/Database.php#L25-L66
用于创建Predis\Client
实例的Laravel 代码:https:
//github.com/laravel/framework/blob/v5.3.28/src/Illuminate/Redis/Database.php#L25-L66
回答by ramesh.mimit
For AWS elasticcache redis cluster the above configuration did not work, however below are working for me. Also mentioned in the documentation: https://laravel.com/docs/5.4/redis#configuration
对于 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,
],
],
],
],
回答by CenterOrbit
Related: Laravel + Redis Cache via SSL?
To which I've answered here: https://stackoverflow.com/a/48876398/663058
我在这里回答过:https: //stackoverflow.com/a/48876398/663058
Relevant details below:
相关详情如下:
If you have clustering andTLS then you'll need a the following config (tested with AWS Elasticache):
如果您有集群和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
]
]
Explaining the above:
解释以上内容:
'client' => 'predis'
: This specifies the PHP Library Redis driver to use (predis).'cluster' => 'redis'
: This tells Predis to assume server-side clustering. Which just means "follow redirects" (e.g.-MOVED
responses). When running with a cluster, a node will respond with a-MOVED
to the node that you must ask for a specific key.- If you don't have this enabled with Redis Clusters, Laravel will throw a
-MOVED
exception 1/ntimes, nbeing the number of nodes in Redis cluster (it'll get lucky and ask the right node every once in awhile)
- If you don't have this enabled with Redis Clusters, Laravel will throw a
'clusters' => [...]
: Specifies a list of nodes, but setting just a 'default' and pointing it to the AWS 'Configuration endpoint'will let it find any/all other nodes dynamically (recommended for Elasticache, because you don't know when nodes are comin' or goin').'options'
: For Laravel, can be specified at the top-level, cluster-level, and node option. (they get combined in Illuminate before being passed off to Predis)'parameters'
: These 'override' the default connection settings/assumptions that Predis uses for new connections. Since we set them explicitly for the 'default' connection, these aren't used. But for a cluster setup, they are critical. A 'master' node may send back a redirect (-MOVED
) and unless the parameters are set forpassword
andscheme
it'll assume defaults, and that new connection to the new node will fail.
'client' => 'predis'
:这指定要使用的 PHP 库 Redis 驱动程序 (predis)。'cluster' => 'redis'
:这告诉 Predis 假设服务器端集群。这只是意味着“跟随重定向”(例如-MOVED
响应)。与集群一起运行时,节点将响应-MOVED
您必须请求特定密钥的节点。- 如果您没有在 Redis Clusters 中启用此功能,Laravel 将抛出
-MOVED
1/ n次异常,n是 Redis 集群中的节点数(它会很幸运并每隔一段时间询问正确的节点)
- 如果您没有在 Redis Clusters 中启用此功能,Laravel 将抛出
'clusters' => [...]
:指定节点列表,但仅设置一个“默认”并将其指向AWS 的“配置端点”将使其动态查找任何/所有其他节点(推荐用于 Elasticache,因为您不知道节点何时到来)或去')。'options'
:对于Laravel,可以在top-level、cluster-level、node选项中指定。(在传递给 Predis 之前,它们在 Illuminate 中组合在一起)'parameters'
:这些“覆盖” Predis 用于新连接的默认连接设置/假设。由于我们为“默认”连接明确设置了它们,因此不使用它们。但对于集群设置,它们至关重要。“主”节点可能会发回重定向 (-MOVED
) 并且除非设置了参数password
并且scheme
它将采用默认值,否则到新节点的新连接将失败。
回答by Pinak Saha
Please refer to [ https://laravel.com/docs/5.5/redis].
请参考 [ https://laravel.com/docs/5.5/redis]。
Make sure you have the proper library
确保你有合适的库
composer require predis/predis
In config/database.php as well as config/queue.php [ if your queue is also using clustered reddis]
在 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,
],
],
],
]
回答by abbood
this worked for me:
这对我有用:
'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'
],
]
]
to see how I got there, see my answer here
查看我是如何到达那里的,请在此处查看我的答案