Redis Cluster
Redis3.0之后,节点之间通过去中心化的方式提供了完整的sharding(分片)、replication(复制)、failover解决方案,称为 Redis Cluster。
1、所有redis节点(包括主和从)彼此互联(两两通信)。
2、集群中的高可用逻辑,通过主节点的过半选举实现主从替换。
3、客户端与redis-cluster连接,无需再关心分片的计算,客户端不在关心分片的计算逻辑,内部分发分布式数据(内部有分片计算逻辑),客户端将key交给redis节点后,集群内部判断key值的正确存储位置,转发存储;
hash slot(哈希槽)
Redis Cluster在设计中没有使用一致性哈希(Consistency Hashing),而是引入哈希槽(hash slot)来实现;一个 Redis Cluster包含16384(0~16383)个哈希槽,存储在Redis Cluster中的所有key都会被映射到这些slot中,集群中的每个key都属于这16384个哈希槽中的一个,集群使用公式slot=CRC16(key)%16384来计算key属于哪个槽。
Redis群集中的每个节点都负责哈希槽的子集,因此,例如,您可能有一个包含3个节点的群集,其中:
节点A包含从0到5500的哈希槽。
节点B包含从5501到11000的哈希槽。
节点C包含从11001到16383的哈希槽。
这样可以轻松添加和删除集群中的节点。例如,如果我想添加一个新节点D,则需要将一些哈希槽从节点A,B,C移到D。类似地,如果我想从群集中删除节点A,则只需移动A所服务的哈希槽到B和C。当节点A为空时,我可以将其从群集中完全删除。
槽道原理
当连接redis集群中任意一个已知的节点想通过set key value命令来保存数据,或get key来获取数据,首先会根据key值,通过CRC16(key)%16384,算出这个key应该落入的槽道号,接下来就只需要找到是哪个节点管理这个槽道号,就可以在这个节点操作了。
有两种可能,要么当前连接的节点就管理着这个槽道号,在当前节点直接set就可以了。要么这个节点不管理这个槽道号,需要寻找对的节点。如果想判断槽道是否归某个节点管理,就需要使用一个能标记的东西将槽道和节点联系起来,在redis集群中,有两个关键类以及里面的两个关键属性(clusterNode和clusterState的slots属性)。
(1)clusterNode类的slots属性:clusterNode类对应一个节点的信息,类似cluster nodes命令得到的单个节点的信息,包括节点id、ip、端口等信息,它有一个关键属性slots,类型是一个2048位的byte数组(二进制位序列数组),对应就是16384个bit位,通过这个数组bit是1或0,来决定节点是否拥有槽道的管理权,每个节点都有自己的这个数组。
(2)clusterState类的slots属性:clusterState类记录了集群状态的信息,类似cluster info命令得到的集群信息。它有一个关键的属性slots,类型是一个16384位长度的clusterNode数组(索引数组),它记录着整个集群的槽道信息,根据这个数组的下标,可以找到对应的节点。
当前连接的节点根据key计算出来的槽道号,在二进制位序列数组查找该槽道号的值,如果是1,表示当前节点管理了这个槽道,如果是0,则没有管理这个槽道,需要查找索引数组对应的槽道号被哪个节点管理。