Redis 代理方案 Twemproxy

谈谈在各大公司广泛使用的Redis代理方案——Twemproxy

Redis现在使用得非常广泛,但是Redis单例比较大的局限——单例使用到的内存一般最多10~20GB。这无法支撑大型线上业务系统的需求。而且也会造成资源的利用率过低——现在企业使用的内存肯定是Redis单例使用到内存的好几倍。

为了解决单机承载能力不足的问题,就必然会使用到多个Redis构成的集群。

Redis 集群技术

客户端分片

客户端分片将分片工作放到了业务层,程序代码根据预先设置的路由规则,直接对多个Redis实例进行分布式访问。

这样的好处是,不依赖于第三方分布式中间件,实现方法和代码都自己掌控,可随时调整,不用担心踩到坑;同时,这种分片机制的性能比代理式更好(少了一个中间分发环节)。

但是缺点也比较多:首先这是一种静态分片技术。Redis实例的增减,都得手工调整分片程序,其次,虽然少了中间分发环节,但是导致升级麻烦,对研发人员的个人依赖性强——需要有较强的程序开发能力做后盾。

所以,这种方式下,可运维性较差。出现故障,定位和解决都得研发和运维配合着解决,故障时间变长。

代理分片

代理分片将分片工作交给专门的代理程序来做。代理程序接收到来自业务程序的数据请求,根据路由规则,将这些请求分发给正确的Redis实例并返回给业务程序。因此整个代理对业务层是透明的,业务层只需要把这个一个单纯的Redis实例使用即可。同时因为Redis请求都打到了代理上,我们很容易在代理的基础上进行进一步的分析工作。

虽然会因此带来些性能损耗,但对于Redis这种内存读写型应用,相对而言是能容忍的。

基于该机制的开源产品Twemproxy,便是其中代表之一,应用非常广泛。

Redis Cluster

在这种机制下,没有中心节点(和代理模式的重要不同之处)。

这样的好处是,Redis Cluster将所有Key映射到16384个Slot中,集群中每个Redis实例负责一部分,业务程序通过集成的Redis Cluster客户端进行操作。客户端可以向任一实例发出请求,如果所需数据不在该实例中,则该实例引导客户端自动去对应实例读写数据。

但是缺点也是同样存在,这是一个非常重的方案,Redis Cluster的成员管理(节点名称、IP、端口、状态、角色)等,都通过节点之间两两通讯,定期交换并更新。缺少了Redis单例的“简单、可依赖”的特点

Twemproxy

Twemproxy是上面代理分片构造Redis集群的一个开源解决方案。

TwemProxy采用中间层代理的方式,在不改动服务器端程序的情况下,使得集群管理更简单、轻量和有效。Twemproxy 通过引入一个代理层,将其后端的多台 Redis实例进行统一管理与分配,使应用程序只需要在Twemproxy 上进行操作,而不用关心后面具体有多少个真实的 Redis实例。

优势

  • 单线程工作,用C语言开发
  • 直接支持大部分Redis指令,所以对于业务层可以透明使用
  • 路由策略多样,支持HashTag, 通过HashTag可以自己设定将同一类型的key映射到同一个实例上去
  • 减少与redis的直接连接数,保持与redis的长连接,可设置代理与后台每个redis连接的数目
  • 自带一致性hash算法,能够将数据自动分片到后端多个redis实例上
  • 支持redis pipelining request,将多个连接请求,组成reids pipelining统一向redis请求。
  • 高效;对连接的管理采用epoll机制,内部数据传输采用“Zero Copy”技术,以提高运行效率

高可用方案

因为Twemproxy本身是单点,所以需要用Keepalived做高可用方案。

Keepalived是一种实现高可用的方案,它的功能主要包括两方面:
1)通过IP漂移,实现服务的高可用:服务器集群共享一个虚拟IP,同一时间只有一个服务器占有虚拟IP并对外提供服务,若该服务器不可用,则虚拟IP漂移至另一台服务器并对外提供服务;
2)对LVS应用服务层的应用服务器集群进行状态监控:若应用服务器不可用,则keepalived将其从集群中摘除,若应用服务器恢复,则keepalived将其重新加入集群中。