我有一个带有redis的laravel(5.3)应用程序,用于会话(使用predis)。只要我使用单个redis节点(使用 config / database.php中的 默认方法),一切都可以正常工作。一旦我切换到Redis集群,尽管我开始像50%的时间一样出现MOVED错误(基于谷歌搜索,我知道这应该由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的,我使用的Redis天青缓存集群高级P1,2个碎片(如所描述的在这里)。
更新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)], ], ],
非常感谢您的帮助:)
'cluster' => true
'options' => ['cluster' => 'redis']
default
'options' => [ 'cluster' => 'redis', 'parameters' => ['password' => env('REDIS_PASSWORD', null)], ]
在redis配置中,您可以设置到多个redis实例的多个连接。该cluster选项告诉Laravel如何处理这些多个定义的连接。
cluster
如果cluster设置为false,Laravel将为\Predis\Client每个连接创建单独的实例。每个连接都可以单独访问,并且与另一个连接没有任何关系。
false
\Predis\Client
如果cluster设置为true,Laravel将\Predis\Client使用所有定义的连接创建一个聚合实例。如果没有其他配置,这就是一种“伪”集群。它使用客户端分片来分发密钥空间,并且可能需要外部监视和维护以确保适当的密钥负载平衡。
true
但是,您遇到的问题是,Azure实现了(大概是)真实的服务器端Redis群集,该群集处理密钥空间的自动分片。在这种情况下,节点相互了解并相互交谈,并且可能会上下波动。这是MOVED和ASK反应从何而来。
MOVED
ASK
该Predis库可以自动处理这些响应,但是仅在您告知需要时才可以。在这种情况下,您需要告诉Predis客户端它需要处理集群,这是由Laravel通过配置中的options阵列完成的redis。
Predis
options
redis
在redis配置上,options密钥应该是您的连接的同级(即default),而不是孩子。此外,选项应key => value成对指定。
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可以处理多个节点的实例,而cluster下键options阵列会告诉实例它需要处理服务器端集群,而不是客户端集群。
Predis\Client
原始连接参数(包括身份验证)不会与通过-MOVED和-ASK响应发现的新节点的连接共享。因此,您以前从-MOVED响应中得到的任何错误现在都将转换为NOAUTH错误。但是,服务器端'cluster'配置允许'parameters'同级,该同级定义了与新发现的节点一起使用的参数列表。在这里您可以将auth参数与新节点一起使用。
-MOVED
-ASK
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)], ], ],
公平的警告,这就是我刚刚从研究和代码潜水中获得的所有信息。虽然我将Redis与Laravel结合使用,但尚未使用服务器端集群(因此),因此这可能仍然行不通。
我在研究时遇到了一些有用的信息:
似乎您没有将Predis配置为使用redis- cluster,而是将其与普通的旧客户端分片逻辑(这也是默认行为)一起使用。您应该配置客户端,将选项集群设置为值redis,以使客户端知道它必须与redis- cluster一起使用。快速示例: $client = new Predis\Client([$node1, $node2, ...], ['cluster' => 'redis']); 这样做将使客户端可以自动处理来自Redis节点的-MOVED或-ASK响应。
似乎您没有将Predis配置为使用redis- cluster,而是将其与普通的旧客户端分片逻辑(这也是默认行为)一起使用。您应该配置客户端,将选项集群设置为值redis,以使客户端知道它必须与redis- cluster一起使用。快速示例:
$client = new Predis\Client([$node1, $node2, ...], ['cluster' => 'redis']);
这样做将使客户端可以自动处理来自Redis节点的-MOVED或-ASK响应。
MS文章讨论Redis缓存上的群集:https : //docs.microsoft.com/zh-cn/azure/redis-cache/cache-how-to-premium- clustering#how-do-i-connect-to-my-启用集群缓存
您可以使用与连接到未启用群集的缓存时使用的端点,端口和键相同的端点连接到缓存。Redis在后端管理集群,因此您不必从客户端进行管理。