RedisCluster是在Redis3.0的版本正式推出的,用来解决分布式的需求,同时也可以实现高可用。
RedisCluster可以看成是由多个Redis实例组成的数据集合。客户端不需要关注数据的子集到底存储在哪个节点,只需要关注这个集合整体。
3主3从为例,节点之间两两交互,共享数据分片、节点状态等信息
https://gper.club/articles/7e7e7f7ff7g5egc7g6d
如果是希望数据分布相对均匀的话,我们首先可以考虑哈希后取模。
例如,hash(key)%N,根据余数,决定映射到那一个节点。这种方式比较简单,属于静态的分片规则。但是一旦节点数量变化,新增或者减少,由于取模的N发生变化,数据需要重新分布。
为了解决这个问题,我们又有了一致性哈希算法。
把所有的哈希值空间组织成一个虚拟的圆环(哈希环),整个空间按顺时针方向组织。因为是环形空间,0和2^32-1是重叠的。
节点不一定是均匀地分布的,特别是在节点数比较少的情况下,所以数据不能得到均匀分布!
解决这个问题的办法是引入虚拟节点(VirtualNode)。
Redis既没有用哈希取模,也没有用一致性哈希,而是用虚拟槽来实现的。
Redis创建了16384个槽(slot),每个节点负责一定区间的slot。比如Node1负责0-5460,Node2负责5461-10922,Node3负责10923-16383。
对象分布到Redis节点上时,对key用CRC16算法计算再384,得到一个slot的值,数据落到负责这个slot的Redis节点上。
查看key属于哪个slot:
redis> cluster key xxxx
注意:key与slot的关系是永远不会变的,会变的只有slot和Redis节点的关系。
怎么让相关的数据落到同一个节点上?
key里面加入{hashtag}即可
比如在7291端口的Redis的redis-cli客户端操作:
Jedis等客户端会在本地维护一份slot——node的映射关系,大部分时候不需要重定向,所以叫做smartjedis(需要客户端支持)。
数据迁移
因为key和slot的关系是永远不会变的,当新增了节点的时候,需要把原有的slot分配给新的节点负责,并且把相关的数据迁移过来。
添加新节点(新增一个7297):
新增的节点没有哈希槽,不能分布数据,在原来的任意一个节点上执行:
主从切换原理如下
slave发现自己的master变为FAIL将自己记录的集群currentEpoch加1,并广播FAILOVER_AUTH_REQUEST信息其他节点收到该信息,只有master响应,判断请求者的合法性,并发送FAILOVER_AUTH_ACK,对每一个epoch只发送一次ack尝试failover的slave收集FAILOVER_AUTH_ACK超过半数后变成新Master广播Pong通知其他集群节点。