单机
redis最主要的适用场景:少许数据存储,高速读写访问,数据所有in-momery 的方式来保证高速访问,同时提供数据落地的功能。html
分布式
随着用户量的增加,数据量随之增加,大型网站应用,热点数据量每每巨大,几十G上百G是很正常的事儿,这时候咱们须要横向扩展,多台主机共同提供服务,既分布多个redis协同工做。大体有以下几种集群方案:java
方案一:Redis官方集群方案Redis Cluster
Redis Cluster由3.0版本正式推出,是一种服务器sharding技术,对客户端来讲是彻底透明的。node
Redis Cluster中,Sharding采用slot(槽)的概念,一共分红16384个槽。对于每一个进入Redis的键值对,根据key进行散列,分配到这16384个slot中的某一个中。使用的hash算法也比较简单,就是CRC16后16384取模。redis
Redis集群中的每一个node(节点)负责分摊这16384个slot中的一部分,也就是说,每一个slot都对应一个node负责处理。当动态添加或减小node节点时,须要将16384个槽作个再分配,槽中的键值也要迁移。固然,这一过程,在目前实现中,还处于半自动状态,须要人工介入。算法
Redis集群,要保证16384个槽对应的node都正常工做,若是某个node发生故障,那它负责的slots也就失效,整个集群将不能工做。浏览器
为了增长集群的可访问性,官方推荐的方案是将node配置成主从结构,即一个master主节点,挂n个slave从节点。这时,若是主节点失效,Redis Cluster会根据选举算法从slave节点中选择一个上升为主节点,整个集群继续对外提供服务。这很是相似前篇文章提到的Redis Sharding场景下服务器节点经过Sentinel监控架构成主从结构,只是Redis Cluster自己提供了故障转移容错的能力。服务器
Redis Cluster的新节点识别能力、故障判断及故障转移能力是经过集群中的每一个node都在和其它nodes进行通讯,这被称为集群总线(cluster bus)。它们使用特殊的端口号,即对外服务端口号加10000。例如若是某个node的端口号是6379,那么它与其它nodes通讯的端口号是16379。nodes之间的通讯采用特殊的二进制协议。架构
对客户端来讲,整个cluster被看作是一个总体,客户端能够链接任意一个node进行操做,就像操做单一Redis实例同样,当客户端操做的key没有分配到该node上时,Redis会返回转向指令,指向正确的node,这有点儿像浏览器页面的302 redirect跳转。分布式
Redis Cluster是Redis 3.0之后才正式推出,时间较晚,目前能证实在大规模生产环境下成功的案例还不是不少,须要时间检验。memcached
方案二:Redis Sharding集群
这种方案把sharding彻底放在客户端,每一个redis都是独立的存在,其只要思想是将key进行散列,经过hash函数,不一样的key映射到指定的redis节点上。
jedis已经很好的支持了redis sharding功能:
JedisShardInfo jedisShardInfo1 = new JedisShardInfo(bundle.getString("redis1.ip"), Integer.valueOf(bundle.getString("redis.port"))); JedisShardInfo jedisShardInfo2 = new JedisShardInfo(bundle.getString("redis2.ip"), Integer.valueOf(bundle.getString("redis.port"))); List list = new LinkedList(); list.add(jedisShardInfo1); list.add(jedisShardInfo2); ShardedJedisPool pool = new ShardedJedisPool(config, list); ShardedJedis jedis = pool.getResource();
此模式下的扩容问题,做者给出了解决方案
Redis的做者提出了一种叫作presharding的方案来解决动态扩容和数据分区的问题,实际就是在同一台机器上部署多个Redis实例的方式,当容量不够时将多个实例拆分到不一样的机器上,这样实际就达到了扩容的效果。
拆分过程以下:
1.在新机器上启动好对应端口的Redis实例。 2.配置新端口为待迁移端口的从库。 3.待复制完成,与主库完成同步后,切换全部客户端配置到新的从库的端口。 4.配置从库为新的主库。 5.移除老的端口实例。 6.重复上述过程迁移好全部的端口到指定服务器上。
redis单点问题
对应单台redis咱们可使用master/slaver模式,尽可能不要出现单点,可以在master机出现宕机的状况下,slaver可以从新接管,继续提供服务。
方案三:代理中间件实现集群
twemproxy是目前使用最为普遍的redis代理中间件,twemproxy将客户端发送过来的请求,进行sharding处理后,转发给相应的redis服务器,客户端不直接访问redis服务器,对客户端来讲,后台redis集群是彻底透明的。
twemproxy内部处理是无状态的,因此它自己能够很容易的进行集群,防止出现单点故障。twemproxy后台不只支持redis,还支持memcached。
固然因为使用了中间件代理,相比客户端直接链接服务器,性能上会有一点的影响,性能大概下降了20%-30%左右。
基于Twemproxy的Redis集群方案
方案四:基于Redis的开源分布式服务Codis
Codis是豌豆荚在以上三种方式都不能很好的解决问题的状况下,从新开发的基于Redis的开源分布式服务。
Codis的总体设计:
Pre-sharding slot->[0,1023] Zookeeper Proxy无状态 平滑扩展和缩容 扩容对用户透明
能够看一张总体的架构图:
总结:每一种方案都有它适用的环境,也没有哪一种方案是能够解决任何问题的,方案每每都是根据咱们系统的不断发展不断进行改进的。