使用Twemproxy安装Redis群集,我真的很困惑为什么有些SET命令被MOVED

时间:2015-11-02 09:01:17

标签: php redis twemproxy

我已经使用Redis-Server 3.0.5版(Ubuntu 14.04)设置了Redis-Cluster

为简单起见,我们将忽略复制。我在localhost上运行了三个redis实例,端口7001,7002和7003.它们都是使用此命令成为集群的主人

redis-trib.rb create 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003

我喜欢使用twemproxy

的想法

twemproxy-config.yml

twem-1:
  listen: 127.0.0.1:22121
  hash: fnv1a_64
  distribution: ketama
  redis: true
  preconnect: true
  servers:
  - 127.0.0.1:7001:1
  - 127.0.0.1:7002:1
  - 127.0.0.1:7003:1

我使用nutcracker -c twemproxy-config.yml -d初始化twemproxy然后我可以使用redis-cli -h 127.0.0.1 -p 22121

访问twemproxy

请查看此输入和输出

127.0.0.1:22121> set hello 4542342342424
OK
127.0.0.1:22121> set goodbye 345353535545
(error) MOVED 9354 159.203.136.204:7002

127.0.0.1:22121> get hello
"4542342342424"
127.0.0.1:22121> get goodbye
(error) MOVED 9354 159.203.136.204:7002

我担心这可能无法正常工作。如果我绕过twemproxy并使用redis-cli -c -h 127.0.0.1 -p 7001连接,我可以看到自动转发发生。像这样;

127.0.0.1:7001> get hello
"4542342342424"

127.0.0.1:7001> get goodbye
-> Redirected to slot [9354] located at 127.0.0.1:7002
(nil)

127.0.0.1:7002> set goodbye 3240923842094840
OK

127.0.0.1:7002> get goodbye
"3240923842094840"

参考

Redis Cluster Specification

Interesting read at code.hootsuite.com about use of twemproxy(大约一半的页面)

终极目标

我的最终目标是使用redis集群在负载均衡器后面的多个Web服务器上存储PHP会话数据。在php.ini中我会session.save_handler = redissession.save_path = tcp://127.0.0.1:22121(twemproxy实例将在每个Web服务器上运行)。 PHP会话配置位尚未设置。

我希望我有意义。我使用正确的哈希码吗?我真的希望看到twemproxy回复确定而不是 MOVED

谢谢!

更新

感谢@the-real-bill的回答我在两个节点上设置了redis,标准redis运行端口6380和sentinel运行端口16380,一个是master,另一个是slave。看着日志,一切看起来都不错。

我查看了predisphpredis

这是我仍然有点不确定的一点,我相信我会有更多的时间来解决这个问题。查询只能写入主服务器,查询只能从从服务器读取。我们有Sentinel根据可用性推广一个或另一个 - 会话处理程序如何知道它可以写入哪一个?当然,我需要提供两个IP地址..

2 个答案:

答案 0 :(得分:2)

Redis群集是一种客户端感知模式。在Redis群集中,客户端总是大多数连接到给定密钥的“正确”节点。 MOVED回复告诉客户端哪个节点服务该密钥。最初,客户端需要在连接上提取当前拓扑,然后在获得MOVED时进行更新。这是性能最高的模式,因为没有涉及代理。

但是,这意味着您无法在Redis群集设置前使用任何现有代理。正如您所看到的,Twemproxy只需代理某些命令,并拒绝其他命令。为了让Twemproxy能够处理这个问题,它需要实现集群API并完成客户端所做的一切。这是不行的,你也不应该期望它尽快这样做。任何其他代理,如nginx或HAProxy都需要做同样的事情(假设有openresty或你可以在Nginx中执行此操作的自定义模块比其他模块更容易)。

此外,最后我检查了PHP客户端不支持Redis群集。

但是,对于您的用例,我怀疑您确实需要Redis群集。使用Sentinel在Pod(主站+从站)中配置Redis以管理故障转移以及客户端Sentinel支持可能会很好地满足您的需求。我相信PRedis有支持,但我确信phpredis没有。

如果您对运行共享集群的复杂性有所了解,那么请使用Twemproxy后面的常规Redis + Sentinel,并让Twemproxy通过您告诉它使用的共享算法进行连接。这是尝试使用Tweproxy的另一个问题 - 它执行Redis Cluster所做的但作为代理。所以实际上你会尝试两次分割数据集。我相信你能想象出灾难性的方式。 ;)

如果您无法获得适当的支持或者不希望Twemproxy管理共享,您的最终选择(自己添加客户端支持)是设置由sentinel配置的代理。例如,您可以使用配置为指向主服务器的HAProxy。在故障转移上,Sentinel可以为您执行脚本。

然后,此脚本可以更新您的HAProxy配置并为您重新启动它,从而确保正确的重新连接行为。有很多方法可以做到这一点,谷歌搜索它,结合Redis Sentinel文档并将它们应用到您的环境中将为您显示路径。

答案 1 :(得分:0)

您不能同时使用 Redis群集 twemproxy 。在 Redis群集模式下,应该是客户端将请求发送到正确的主服务器。当您从错误的主设备请求密钥时,它将始终发回 MOVE 回复,将您重定向到正确的主设备。