程序员人生 网站导航

Twemproxy来自Twitter的Redis代理

栏目:框架设计时间:2015-01-16 09:03:34
在大量用户大范围使用大型Redis节点的时候,目前从项目本身来看Redis基本上可以说是1个单例的业务。 关于这个项目的散布式我有1个很大的想法,在这个想法下,我不需要去对多线程版本的Redis做任何评估:在这个角度上对我来讲,1个核就像是1台计算机,所以在多核上扩大就相当于散布在计算机之间的集群。多实例是1个无同享的架构。如果我们找到1个可用的方式来分片,那末所有事情就公道了。 :-) 这也是为何集群会成为Redis在2013年的焦点,并且,终究Redis 2.6的发布表现出了很好的稳定性和成熟度,现在正是时候来关注Redis Cluster, Redis Sentinel, 和1些其它期待已久的改进。 但是现实状态是,Redis Cluster目前依然没有发布,正式版还需要几个月的工作。但是我们的用户已需要将数据分片到不同的实例上来做负载均衡,更重要的是为数据取得更大的内存存储。 目前保底的结局方案是客户端分片。客户端分片有很多好处,例如:在客户端和节点之间没有中间层,这就意味着它是1个扩大性很好的设置(主要是线性扩大)。但是要稳定的实现(客户端分片)需要进行1些优化,需要1个同步客户端配置的方式,也需要客户端支持1致性哈希或其它分区算法。 有1个重大消息来自Twitter,世界最大的Redis集群之1部署在Twitter用于为用户提供时间轴数据。所以绝不奇怪这篇文章讨论的项目来自Twitter Open Source部门。 Twemproxy --- Twemproxy是1个快速的单线程代理程序,支持Memcached ASCII协议和更新的Redis协议:  它全部用C写成,使用Apache 2.0 License授权。  项目在Linux上可以工作,而在OSX上没法编译,由于它依赖了epoll API. 我的测试环境为Ubuntu 12.04桌面版。  好吧,闲话少叙。twemproxy到底做了甚么?(注:我将关注Redis到部份,但是该项目也能够对memcached做相同到事情)  1) 在客户端和众多Redis实例间作为代理。  2) 在配置的Redis实例之间进行自动到数据分片。  3) 支持1致性哈希,支持不同到策略和哈希方法。  Twemproxy最了不起的地方就在于它能在节点失败的时候卸载它,然后可以在1段时间以后重新尝试(随即)连接,又或可以严格依照配置文件中写的键与服务器之间对应关系进行连接。这意味着Twemproxy能胜任把Redis当作数据存储(不能容忍节点未命中)的场景,也能够胜任当作缓存来使用,那些允许(它意味着少许,不是说低质量)未命中且高可用的场景。 总结来讲就是:如果你能容忍未命中,那末当有节点失败你的数据或许会存储到其他节点,所以它会是弱1致性的。另外一方面,如果你不能容忍未命中,那末你需要1个具有高可用的实例的方案,例如使用Redis监控的失败自动切换功能。 安装   ---  在深入项目的更多特性之前,有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页面上有足够的文档可让你有1个平滑的初体验。我使用了以下的配置: 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  第1个集群配置为(故障时)节点自动排除,第2个集群则在所有实例上配置了静态映照。  有趣的是,针对同1组服务器你能同时有多个部署。但是在生产环境更合适使用多个示例以利用多核的能力。 单点失效?  ---  还有另外一件有趣的事情,使用这个部署其实不意味着有单点失效问题,你可以通过运行多套twemproxy,让你的客户端连接到第1个可用的实例。  通过使用twemproxy你基本上把分片逻辑和客户端进行了分离。在这类情况下,1个基本的客户端就能够实现目的,分片将完全由代理来处理。 这是1个直接而安全的方法,个人观点。 现在Redis Cluster还不成熟,twemproxy是大多数希望利用Redis集群的用户的好方法。也不要太激动,先看看这类方法的限制 ;) 不足 --- 我认为Twemproxy没有支持批量操作的命令和事物是对的。固然,AFAIK乃至比Redis cluster更严格,反而它对相同的键允许批量操作。 但是恕我直言依照这类方式,分散的集群带来分散的效力,并且将这个挑战带给了初期的用户,而且花费了大量的资源,从大量的实例中汇总数据,得到仅仅是“能用”的结果,而且你将很快开始有严重的负载问题,由于你有太多的时间花费在数据的传输上。 可是有1些批量操作命令还是支持了的。MGET和DEL是处理的非常好的。有趣的是MGET命令在不同的服务器之间切分要求并且返回1个结果。这1点相当酷,或许我以后不能有更好的性能(看以后的吧)。 不管如何,批量操作和事物的不支持的现状意味着Twemproxy不适用于每一个人,特别像Redis cluster本身。特别是它明显不支持EVAL(我认为他们应当支持它!它是多通用的,EVAL被设计可以在代理中工作,是由于键的名字已明确了)。

有待改进的地方 --- 毛病报告机制其实不稳定,发送1个Redis不支持的命令会致使连接被关闭。比如从redis-cli只发送1个‘GET‘其实不会报"参数个数不正确”的毛病,只会致使连接被挂起。 整体看来,服务器返回的其它毛病都可以准确的传给客户端: redis metal: 10000 > get list (毛病)类型操作毛病,键匹配了毛病的值类型 另外1个我想要看到的特性是对自动故障恢复的支持。有很多种替换方案: 1) twemproxy已能够监控实例毛病信息、毛病的数量、在检测出足够多的毛病的情况下断开节点。但是很遗憾twemproxy不能够拿从节点作为替换方案,这样就能够发送1个SLAVE OFNOONE命令来弃用备用节点,而不用只是断开毛病节点。这类情况下twemproxy才是1个具有高可用性的解决方案。 2) 或,我希望twemproxy能够与Redis Sentinel1起协同工作,定期检查Sentinel配置,如果出现故障则更新服务端配置 3) 另外1种替换方案是提供1种热配置twemproxy的方式,1旦节点出故障,Redis Sentinel就可以够切换ASAP代理配置 有很多种替换方案,整体来讲,如果能够提供对HA(高可用性)的底层支持就非常棒了。 性能  --- Twemproxy很快,真的很快,接近直接与Redis通讯的速度。我敢说你用的话最多损失20%的性能。 我对性能唯1的意见是可以有更高效的方法把IMHO MGET命令分发到实例之间 如果twemproxy与所有Redis实例的延迟很相似的话(很有可能),在MGETs命令在同1时间发出的情况下,twemproxy很有可能会在同1时间接收到所有节点的命令,所以我希望看到的是当我在所有实例上运行MGET命令的时候,发送的数量和twemproxy接收到的数量是1致的,但是实际上twemproxy在1秒内只接收到了50%的MGET命令。或许是时候重构twemproxy的应对模块了。 结论 --- 这是个伟大的项目,鉴于Redis Cluster还未发布,我强烈建议有需求的Redis用户试1下Twemproxy 我正打算将它链接到Redis项目网站上,由于我认为Twitter的伙计已用他们的项目为Redis做了不小的贡献,所以... 这是Twitter赢得荣誉!
------分隔线----------------------------
------分隔线----------------------------

最新技术推荐