redisCluster
前言
此篇文章主要介绍分片,主从和哨兵模式会在别的文章中介绍
一、客户端分片
在Redis 3.0之前,redis并没有Redis cluster功能,当时大部分使用的是客户端分片以及第三方工具实现分片集群,比如Jedis,
Jedis的Redis Sharding实现具有如下特点:
- 采用一致性哈希算法(consistent hashing),将key和节点name各自hashing,,然后进行映射匹配,采用的算法是MURMUR_HASH。采用一致性哈希而不是采用简单类似哈希求模映射的主要原因是当增加或减少节点时,不会产生由于重新匹配造成的rehashing。一致性哈希只影响相邻节点key分配,影响量小。
- 为了避免一致性哈希只影响相邻节点造成节点分配压力,ShardedJedis会对每个Redis节点根据名字(没有,Jedis会赋予缺省名字)会虚拟化出160个虚拟节点进行散列。根据权重weight,也可虚拟化出160倍数的虚拟节点。用虚拟节点做映射匹配,可以在增加或减少Redis节点时,key在各Redis节点移动再分配更均匀,而不是只有相邻节点受影响。(就比如ABC3个节点只能映射出ABC3个散列,如果每个ABC可以虚拟出多N个,即上面说的160个(即现在有3*160个可供给映射),那么存进去的数据则会更加的均匀。)
- ShardedJedis支持keyTagPattern模式,即抽取key的一部分keyTag做sharding,这样通过合理命名key,可以将一组相关联的key放入同一个Redis节点,这在避免跨节点访问相关数据时很重要。
优缺点
客户端自己计算数据的key应该在哪个机器上存储和查找,此方法的好处是降低了服务器集群的复杂度,客户端实现数据分片时,服务器是独立的,服务器之前没有任何关联。多数redis客户端库实现了此功能,也叫sharding,这种方式的缺点是客户端需要实时知道当前集群节点的联系信息,同时,当添加一个新的节点时,客户端要支持动态sharding.,多数客户端实现不支持此功能,需要重启redis。另一个弊端是redis的HA需要额外考虑。
二、代理分片
twemproxy
twemproxy处于客户端和服务器的中间,将客户端发来的请求,进行一定的处理后(如sharding),再转发给后端真正的Redis服务器。也就是说,客户端不直接访问Redis服务器,而是通过twemproxy代理中间件间接访问。
参照Redis Sharding架构,增加代理中间件的Redis集群架构如下:
- twemproxy中间件的内部处理是无状态的,它本身可以很轻松地集群,这样可避免单点压力或故障。
- twemproxy又叫nutcracker,起源于twitter系统中redis/memcached集群开发实践,运行效果良好,后代码奉献给开源社区。其轻量高效,采用C语言开发,工程网址是:GitHub - twitter/twemproxy: A fast, light-weight proxy for memcached andredis
twemproxy后端不仅支持redis,同时也支持memcached,这是twitter系统具体环境造成的。
由于使用了中间件,twemproxy可以通过共享与后端系统的连接,降低客户端直接连接后端服务器的连接数量。同时,它也提供sharding功能,支持后端服务器集群水平扩展。统一运维管理也带来了方便。
当然,也是由于使用了中间件代理,相比客户端直连服务器方式,性能上会有所损耗
三、服务端分片(redis cluster)
详细介绍可参照:
http://www.redis.cn/topics/cluster-tutorial.html
http://www.redis.cn/topics/cluster-spec.html
槽
CRC16算法产生的hash值有16bit,该算法可以产生2^16-=65536个值;不同节点之间需要相互交换信息,交换的数据信息,由消息体和消息头组成。
消息头里面有个myslots的char数组,长度为16383/8,这其实是一个bitmap,每一个位代表一个槽,如果该位为1,表示这个槽是属于这个节点的,在消息头中,最占空间的是myslots[CLUSTER_SLOTS/8]。这块的大小是:
16384÷8÷1024=2kb,如果最大使用65536会需要8kb的空间,浪费带宽;