我有一个laravel(5.3)应用程序,其中redis用于会话(使用predis)。只要我使用单个redis节点(使用 config / database.php 中的默认方法),一切正常。一旦我切换到Redis集群,虽然我开始得到MOVED错误,如50%的时间(基于谷歌搜索,我知道这应该由predis管理,但不知何故不是)。
我尝试将群集参数更改为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缓存群集Premium P1,2个分片(如here所述)。
更新2
到目前为止,我还尝试了以下配置变体:
我一直收到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)],
],
],
非常感谢你的帮助:)
答案 0 :(得分:9)
'cluster' => 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集群,它处理密钥空间的自动分片。在这种情况下,节点彼此了解并且彼此交谈,并且可以上下移动。这是MOVED
和ASK
响应的来源。
Predis
库可以自动处理这些响应,但只有当您告诉它需要时才会这样。在这种情况下,您需要告诉Predis
客户端它需要处理群集,这是由Laravel通过options
配置上的redis
数组完成的。
在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',
],
],
cluster
配置下的redis
密钥将告诉Laravel创建一个可以处理多个节点的聚合Predis\Client
实例,以及{{1}下的cluster
密钥数组将告诉该实例它需要处理服务器端集群,而不是客户端集群。
原始连接参数(包括身份验证)不会与通过options
和-MOVED
响应发现的新节点的连接共享。因此,您之前从-ASK
响应中获得的任何错误现在只会转换为-MOVED
错误。但是,服务器端NOAUTH
配置允许'cluster'
兄弟,它定义了与新发现的节点一起使用的参数列表。您可以在此处将auth参数用于新节点。
我相信这看起来像是:
'parameters'
公平警告,这是我刚从研究和代码潜水中得到的所有信息。虽然我已经将Redis与Laravel一起使用,但我还没有使用过服务器端集群,所以这仍然可能无效。
我在调查时发现了一些有用的信息:
Predis问题讨论连接到redis-cluster:
https://github.com/nrk/predis/issues/259#issuecomment-117339028
看起来您没有将Predis配置为使用redis-cluster,而是使用普通的旧客户端分片逻辑(这也是默认行为)。您应该使用值redis配置客户端设置选项集群,让客户端知道它必须与redis-cluster一起使用。快速举例:
'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节点的-MOVED或-ASK响应。
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
您可以使用连接到未启用群集的缓存时使用的相同端点,端口和密钥连接到缓存。 Redis管理后端的群集,因此您无需从客户端管理群集。
用于创建$client = new Predis\Client([$node1, $node2, ...], ['cluster' => 'redis']);
个实例的Laravel代码:
https://github.com/laravel/framework/blob/v5.3.28/src/Illuminate/Redis/Database.php#L25-L66
答案 1 :(得分:0)
对于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,
],
],
],
],
答案 2 :(得分:0)
相关:Laravel + Redis Cache via 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 Library Redis驱动程序(predis)。'cluster' => 'redis'
:这告诉Predis假设服务器端群集。这只是意味着"遵循重定向" (例如-MOVED
回复)。使用群集运行时,节点将使用-MOVED
响应您必须要求输入特定密钥的节点。
-MOVED
例外1 / n 次, n 为该号码Redis集群中的节点(它很幸运,每隔一段时间就会问一次正确的节点)'clusters' => [...]
:指定节点列表,但只设置一个'默认'并将其指向AWS 'Configuration endpoint'将让它动态地找到任何/所有其他节点(推荐用于Elasticache,因为您不知道节点何时出现,或者是goin')。'options'
:对于Laravel,可以在顶级,群集级别和节点选项中指定。 (他们在被传递到Predis之前被合并在Illuminate中)'parameters'
:这些'覆盖' Predis用于新连接的默认连接设置/假设。由于我们明确设置了默认值'连接,这些都没有使用。但对于群集设置,它们至关重要。 A'主人'节点可以发回重定向(-MOVED
),除非为password
和scheme
设置参数,否则它将假设默认值,并且与新节点的新连接将失败。 答案 3 :(得分:0)
请参阅[{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,
],
],
],
]
答案 4 :(得分:0)
答案 5 :(得分:0)
这个结果出现在谷歌的 predis+redis-cluster 中(没有 laravel)。我和我的团队在这个问题上苦苦挣扎了几个小时,所以我把这个答案放在这里给那些在尝试直接连接到 Redis 集群时发现这个页面出现错误的人:
$redis = new Predis\Client(
['tcp://127.0.0.1:6379'],
['cluster' => 'redis']
);