Twemproxy,Twitter 发布的 Redis 代理服务 已翻译 100%

jjj09090 投递于 2013/02/28 18:36 (共 11 段, 翻译完成于 03-06)
阅读 19365
收藏 57
5
加载中
虽然大量用户使用了大型Redis节点集群,从项目本身到角度来看,Redis仍然是一个单实例业务。

关于项目的分布式化我有一个想法,可以不需要再评估Redis的任何多线程版本:我认为从Redis的角度一个CPU核心就像一台计算机,因此在多核心上扩展与在一个多计算机集群上扩展是同样到概念。多实例是无共享的体系机构。只要我们有一个*可靠的*方式进行分片, 理的 :-)

这是为什么Redis Cluster将成为2013年Redis的主要焦点的原因,现在Redis 2.6已经发布并且显示出非常好到稳定性和成熟度,正是合适的机会来专注于Redis Cluster,Redis Sentinel和其它期待已久的改进(局部重新同步)。

Lax
Lax
翻译于 2013/03/04 09:41
1
然而事实是Redis Cluster还不适应于生产环境,仍需要几个月到工作要做。用户需要在多个实例上做数据分片,以分担负载,特别是使用很多计算机来为数据提供大量的RAM——这个需求依然存在。

目前惟一的选择是客户端分片。客户端分片有一个优势:由于没有客户端和节点之间的中间层,不需要对请求进行路由,所以是一个可扩展的配置(主要是线性扩展)。然而要稳定的实现(客户端分片)需要进行一些优化,需要一个同步客户端配置的方式,也需要客户端支持一致性哈希或其它分区算法。

有一个重大消息来自Twitter,世界最大的Redis集群之一部署在Twitter用于为用户提供时间轴数据。所以毫不奇怪这篇文章讨论的项目来自Twitter Open Source部门。
Lax
Lax
翻译于 2013/03/04 14:30
1
Twemproxy
---

Twemproxy是一个快速的单线程代理程序,支持Memcached ASCII协议和更新的Redis协议:

它全部用C写成,使用Apache 2.0 License授权。

项目在Linux上可以工作,而在OSX上无法编译,因为它依赖了epoll API.

我的测试环境为Ubuntu 12.04桌面版。

好吧,闲话少叙。twemproxy到底做了什么?(注:我将关注Redis到部分,但是该项目也可以对memcached做相同到事情)

1) 在客户端和众多Redis实例间作为代理。
2) 在配置的Redis实例之间进行自动到数据分片。
3) 支持一致性哈希,支持不同到策略和哈希方法。

Lax
Lax
翻译于 2013/03/04 14:39
1

Twemproxy最了不起的地方就在于它能在节点失败的时候卸载它,然后可以在一段时间以后重新尝试(随即)连接,又或者可以严格按照配置文件中写的键与服务器之间对应关系进行连接。这意味着Twemproxy能胜任把Redis当做数据存储(不能容忍节点未命中)的场景,也能够胜任当做缓存来使用,那些允许(它意味着少量,不是说低质量)未命中且高可用的场景。

总结来说就是:如果你能容忍未命中,那么当有节点失败你的数据也许会存储到其他节点,所以它会是弱一致性的。另一方面,如果你不能容忍未命中,那么你需要一个拥有高可用的实例的方案,例如使用Redis监控的失败自动切换功能。

jjj09090
jjj09090
翻译于 2013/03/06 00:55
1
安装 
---

在深入项目的更多特性之前,有一个好消息,它在Linux上非常容易构建。好吧,没有Redis那么简单,但是……你仅仅需要简单按照下面的几步操作:

apt-get install automake
apt-get install libtool
git clone git://github.com/twitter/twemproxy.git
cd twemproxy
autoreconf -fvi
./configure --enable-debug=log
make
src/nutcracker -h

它的配置也非常简单,在项目的github页面上有足够的文档可以让你有一个平滑的初体验。我使用了如下的配置:

redis1:
  listen: 0.0.0.0:9999
  redis: true
  hash: fnv1a_64
  distribution: ketama
  auto_eject_hosts: true
  timeout: 400
  server_retry_timeout: 2000
  server_failure_limit: 1
  servers:
   - 127.0.0.1:6379:1
   - 127.0.0.1:6380:1
   - 127.0.0.1:6381:1
   - 127.0.0.1:6382:1

redis2:
  listen: 0.0.0.0:10000
  redis: true
  hash: fnv1a_64
  distribution: ketama
  auto_eject_hosts: false
  timeout: 400
  servers:
   - 127.0.0.1:6379:1
   - 127.0.0.1:6380:1
   - 127.0.0.1:6381:1
   - 127.0.0.1:6382:1

第一个集群配置为(故障时)节点自动排除,第二个集群则在所有实例上配置了静态映射。

有趣的是,针对同一组服务器你能同时有多个部署。然而在生产环境更适合使用多个示例以利用多核的能力。
Lax
Lax
翻译于 2013/03/04 21:40
1
单点失效?
---

还有另一件有趣的事情,使用这个部署并不意味着有单点失效问题,你可以通过运行多套twemproxy,让你的客户端连接到第一个可用的实例。

通过使用twemproxy你基本上把分片逻辑和客户端进行了分离。在这种情况下,一个基本的客户端就可以实现目的,分片将完全由代理来处理。

这是一个直接而安全的方法,个人观点。

现在Redis Cluster还不成熟,twemproxy是大多数希望利用Redis集群的用户的好方法。也不要太激动,先看看这种方法的限制 ;)
Lax
Lax
翻译于 2013/03/04 21:49
1

不足
---

我认为Twemproxy没有支持批量操作的命令和事物是对的。当然,AFAIK甚至比Redis cluster更严格,反而它对于相同的键允许批量操作。

但是恕我直言按照这种方式,分散的集群带来分散的效率,并且将这个挑战带给了早期的用户,而且花费了大量的资源,从大量的实例中汇总数据,得到仅仅是“能用”的结果,而且你将很快开始有严重的负载问题,因为你有太多的时间花费在数据的传输上。

jjj09090
jjj09090
翻译于 2013/03/06 01:20
1

可是有一些批量操作命令还是支持了的。MGET和DEL是处理的非常好的。有趣的是MGET命令在不同的服务器之间切分请求并且返回一个结果。这一点相当酷,也许我以后不能有更好的性能(看以后的吧)。

无论如何,批量操作和事物的不支持的现状意味着Twemproxy不适用于每个人,特别像Redis cluster本身。特别是它显然不支持EVAL(我认为他们应该支持它!它是多通用的,EVAL被设计可以在代理中工作,是因为键的名字已经明确了)。

jjj09090
jjj09090
翻译于 2013/03/06 01:36
1

有待改进的地方
---

错误报告机制并不稳定,发送一个Redis不支持的命令会导致连接被关闭。比如从redis-cli只发送一个‘GET‘并不会报"参数个数不正确”的错误,只会导致连接被挂起。

总体看来,服务器返回的其它错误都可以准确的传给客户端:

redis metal: 10000 > get list
(错误)类型操作错误,键匹配了错误的值类型

另外一个我想要看到的特性是对自动故障恢复的支持。有很多种替代方案:

1) twemproxy已经能够监控实例错误信息、错误的数量、在检测出足够多的错误的情况下断开节点。但是很遗憾twemproxy不能够拿从节点作为替代方案,这样就可以发送一个SLAVE OFNOONE命令来弃用备用节点,而不用只是断开错误节点。这种情况下twemproxy才是一个具有高可用性的解决方案。

2) 或者,我希望twemproxy能够与Redis Sentinel一起协同工作,定期检查Sentinel配置,如果出现故障则更新服务端配置

3) 另外一种替代方案是提供一种热配置twemproxy的方式,一旦节点出故障,Redis Sentinel就能够切换ASAP代理配置

有很多种替代方案,总体来说,如果能够提供对HA(高可用性)的底层支持就非常棒了。

LannikCooper
LannikCooper
翻译于 2013/03/05 15:10
1
性能

---

Twemproxy很快,真的很快,接近直接与Redis通讯的速度。我敢说你用的话最多损失20%的性能。

我对性能唯一的意见是可以有更高效的方法把IMHO MGET命令分发到实例之间

如果twemproxy与所有Redis实例的延迟很相似的话(很有可能),在MGETs命令在同一时间发出的情况下,twemproxy很有可能会在同一时间接收到所有节点的命令,所以我希望看到的是当我在所有实例上运行MGET命令的时候,发送的数量和twemproxy接收到的数量是一致的,但是实际上twemproxy在一秒内只接收到了50%的MGET命令。也许是时候重构twemproxy的应答模块了。

LannikCooper
LannikCooper
翻译于 2013/03/05 15:48
1
本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接。
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。
加载中

评论(11)

n
nibilly
jedis 连Twemproxy,一直异常:connection reset!
怎么解决,楼主
Si2
Si2
增加节点了,怎么找到那些找不到的key,来处理呢
sweetvvck
sweetvvck
@onetwothree , 你连接redis的端口错了,启动后有个nc_stats.c:851 m 3 listening on '0.0.0.0:22222',还有一个nc_proxy.c:206 p 8 listening on '127.0.0.1:55555' in redis pool 0 'alpha' with 2 servers,应该连接下边这个
onetwothree
onetwothree
我安装的twemproxy-master.zip,装好后连接到redis,执行get命令报错如下
Error: Protocol error, got "{" as reply type byte
用客户端连接,也看不到库里的内容,请问怎么解决啊?急!!!
changmingY
changmingY
twemproxy是否可以保证数据的一致性,比如有2个memcache节点,其中一个当掉后,此时取数据时,会从另外一个中取出想要的数据?
经过测试,没有成功。
在项目主页中,有这样一句,不知如何理解?
Shard data automatically across multiple servers.
youzicha
youzicha

引用来自“jjj09090”的评论

引用来自“youzicha”的评论

我在虚拟机上安装了twemproxy,使用的是nutcracker-0.2.2.tar。配置文件如下:

lpha:
listen: 127.0.0.1:22121
hash: fnv1a_64
distribution: ketama
auto_eject_hosts: true
redis: true
server_retry_timeout: 2000
server_failure_limit: 1
servers:
- 127.0.0.1:6379:1
- 127.0.0.1:6380:1
- 127.0.0.1:6381:1

三个redis都启动时,服务正常。当我把 127.0.0.1:6379停掉时,该服务节点不自动摘除,执行set命令时一直有服务拒绝的命令。

[root@localhost redis]# ./redis-cli -p 22121 set 1 1
(error) ERR Connection refused
当我把故障的redis恢复后,发现服务正常了。结果全部是OK
以上测试可以看出,故障节点没有自动摘除。
请问专家,这是为何?我没有配置好?

server_retry_timeout: 2000->60000
server_failure_limit: 1->0

试试修改以上两个配置,第一个retry的间隔时间要拉长,不然你的nutcracker一直在重试连接,自然一直摘不掉机器;第二个容忍的错误数可以设置成0容忍,就是说有错误立马摘掉这个机器。

我把server_retry_timeout: 20000000这个重连时间改的更长了
这次真的摘除了~谢谢啊!
原来这个参数代表的是发现故障后,恢复连接间隔时间,我还一直以为重试是内部机制呢,原来不是。。这个有点坑爹
youzicha
youzicha

引用来自“jjj09090”的评论

引用来自“youzicha”的评论

我在虚拟机上安装了twemproxy,使用的是nutcracker-0.2.2.tar。配置文件如下:

lpha:
listen: 127.0.0.1:22121
hash: fnv1a_64
distribution: ketama
auto_eject_hosts: true
redis: true
server_retry_timeout: 2000
server_failure_limit: 1
servers:
- 127.0.0.1:6379:1
- 127.0.0.1:6380:1
- 127.0.0.1:6381:1

三个redis都启动时,服务正常。当我把 127.0.0.1:6379停掉时,该服务节点不自动摘除,执行set命令时一直有服务拒绝的命令。

[root@localhost redis]# ./redis-cli -p 22121 set 1 1
(error) ERR Connection refused
当我把故障的redis恢复后,发现服务正常了。结果全部是OK
以上测试可以看出,故障节点没有自动摘除。
请问专家,这是为何?我没有配置好?

server_retry_timeout: 2000->60000
server_failure_limit: 1->0

试试修改以上两个配置,第一个retry的间隔时间要拉长,不然你的nutcracker一直在重试连接,自然一直摘不掉机器;第二个容忍的错误数可以设置成0容忍,就是说有错误立马摘掉这个机器。

server_retry_timeout: 60000
server_failure_limit: 0
---------------------
配置已经修改并重新启动,还是没有摘掉
[root@localhost redis]# ./redis-cli -p 22121 set 5 1
(error) ERR Connection refused
[root@localhost redis]# ./redis-cli -p 22121 set 9 1
OK
[root@localhost redis]# ./redis-cli -p 22121 set 10 1
OK
[root@localhost redis]# ./redis-cli -p 22121 set a 1
(error) ERR Connection refused
jjj09090
jjj09090

引用来自“youzicha”的评论

我在虚拟机上安装了twemproxy,使用的是nutcracker-0.2.2.tar。配置文件如下:

lpha:
listen: 127.0.0.1:22121
hash: fnv1a_64
distribution: ketama
auto_eject_hosts: true
redis: true
server_retry_timeout: 2000
server_failure_limit: 1
servers:
- 127.0.0.1:6379:1
- 127.0.0.1:6380:1
- 127.0.0.1:6381:1

三个redis都启动时,服务正常。当我把 127.0.0.1:6379停掉时,该服务节点不自动摘除,执行set命令时一直有服务拒绝的命令。

[root@localhost redis]# ./redis-cli -p 22121 set 1 1
(error) ERR Connection refused
当我把故障的redis恢复后,发现服务正常了。结果全部是OK
以上测试可以看出,故障节点没有自动摘除。
请问专家,这是为何?我没有配置好?

server_retry_timeout: 2000->60000
server_failure_limit: 1->0

试试修改以上两个配置,第一个retry的间隔时间要拉长,不然你的nutcracker一直在重试连接,自然一直摘不掉机器;第二个容忍的错误数可以设置成0容忍,就是说有错误立马摘掉这个机器。
youzicha
youzicha
我在虚拟机上安装了twemproxy,使用的是nutcracker-0.2.2.tar。配置文件如下:

lpha:
listen: 127.0.0.1:22121
hash: fnv1a_64
distribution: ketama
auto_eject_hosts: true
redis: true
server_retry_timeout: 2000
server_failure_limit: 1
servers:
- 127.0.0.1:6379:1
- 127.0.0.1:6380:1
- 127.0.0.1:6381:1

三个redis都启动时,服务正常。当我把 127.0.0.1:6379停掉时,该服务节点不自动摘除,执行set命令时一直有服务拒绝的命令。

[root@localhost redis]# ./redis-cli -p 22121 set 1 1
(error) ERR Connection refused
当我把故障的redis恢复后,发现服务正常了。结果全部是OK
以上测试可以看出,故障节点没有自动摘除。
请问专家,这是为何?我没有配置好?
Railgun
Railgun
我以为出了个梯子给我们用……
返回顶部
顶部