Redis的数据量与日俱增,越来越多的公司在使用它。它不仅用于缓存,也倾向于用于存储。这必将促进集群的发展。各个公司也在收集自己的集群解决方案。目前业界广泛使用的集群架构有以下几种,其中大部分采用分片技术来解决单实例内存增加带来的一系列问题。本文简单介绍五种方案:官方集群方案twemproxy代理方案sentinel模式codis客户端分片官方cluser方案从redis3.0版本开始支持redis-cluster集群,redis-cluster采用无中心结构,每个节点保存数据和整个集群状态,每个节点连接到其他节点。redis-cluster是一种服务器端分片技术。redis-cluster架构图redis-cluster特点:每个节点与n-1个节点通信,称为集群总线(clusterbus)。他们使用了一个特殊的端口号,也就是对外服务的端口号加上10000。因此,需要维护这个集群各个节点的信息,否则整个集群不可用,内部使用了特殊的二进制协议以优化传输速度和带宽。redis-cluster将所有物理节点映射到[0,16383]槽(slot),cluster负责维护node--slot--value。集群预分了16384个桶。当需要向redis集群中插入数据时,根据CRC16(KEY)mod16384的值决定将key放入哪个bucket中。客户端直接连接redis节点。它不需要连接到集群中的所有节点,只需连接到集群中任何可用的节点即可。redis-trib.rb脚本(rub语言)是一个集群管理工具,可以自动添加节点、规划槽位、迁移数据等一系列操作。一个节点的故障只有在集群中超过一半的节点检测到故障时才会生效。整个集群被视为一个整体,客户端可以连接到任意一个节点进行操作。当客户端操作的key没有分配给节点时,redis会返回转向命令指向正确的节点。为了增加集群的可访问性,官方推荐的方案是将节点配置为master-slave结构,即一个master主节点和n个slave从节点。如果master节点出现故障,redis集群会根据选举算法选择其中一个slave节点成为master节点,整个集群继续对外提供服务。twemproxy代理解决方案twemproxy代理架构图:https://github.com/twitter/twemproxyRedis代理中间件twemproxy是一种使用中间件进行分片的技术。twemproxy处于客户端和服务器的中间。客户端发送的请求处理后(分片),转发给后端真正的redis服务器。也就是说客户端不直接访问redis服务器,而是通过twemproxy代理中间件间接访问。减少了客户端直接连接到后端服务器的连接数,支持服务器集群的水平扩展。twemproxy中间件内部处理是无状态的,可以很方便的自己集群,避免了单点压力或故障。Twemproxy,又称胡桃夹子,起源于Twitter系统中redis和memcached集群的轻量级代理。从上面的架构图我们可以看出twemproxy是单点的,很容易给它造成很大的压力,所以通常会结合keepalived来实现twemproxy的高可用。这个时候通常只有一个twemproxy在工作,另外一个在备机中。一个挂了,vip自动漂移,备用机接管。关于keepalived的使用,可以上网查资料。codiscodis是一个分布式的Redis解决方案,由豌豆荚开源。对于上层应用,连接codis代理和连接原来的redis服务器没有明显区别。上层应用可以像单机redis一样使用,而codis底层会做请求的转发,不停的数据迁移等工作,后面的一切对前端客户端都是透明的,可以简单的认为后面的连接是一个无限内存的redis服务。客户端分片和分区的逻辑是在客户端实现的,由客户端选择请求哪个节点。该方案可以参考一致性哈希,通常适用于用户完全控制客户端行为的场景。哨兵模式哨兵(Sentinel)是Redis的一种高可用解决方案:由一个或多个哨兵实例组成的哨兵系统,可以监控任意数量的主服务器和这些主服务器下的所有从服务器,并在被监控的主服务器进入时离线状态,它会自动将离线主服务器下的一个从服务器升级为新的主服务器。例如:Server1下线后:将Server2升级为新的主服务器:Sentinel工作原理每个Sentinel每秒向其已知的Master、Slave和其他Sentinel实例发送一次PING命令。如果实例与PING命令的最后一个有效回复之间的时间超过down-after-milliseconds选项指定的值,则该实例将被Sentinel标记为主观离线。如果一个Master被标记为主观下线,则所有监控该Master的Sentinel必须每秒确认一次该Master确实进入了主观下线状态。当足够数量的Sentinels(大于或等于配置文件中指定的值)确认Master在指定时间范围内确实进入主观下线状态时,Master将被标记为客观下线。正常情况下,每个Sentinel每隔10秒就会向它认识的所有Master和Slave发送INFO命令。当Master被Sentinel标记为客观下线后,Sentinel向下线Master的所有slave发送INFO命令的频率将从每10秒一次变为每秒一次。如果没有足够的Sentinels同意Master下线,则Master的客观下线状态将被移除。如果Master再次向Sentinel的PING命令返回一个有效值,Master的主观离线状态将被解除。总结:没有最好的方案,只有最合适的。根据自己的需求选择合适的方案才是王道!
