Redis之集群(cluster)
Redis集群是Redis提供的分布式数据库方案,集群通过分片来进行数据共享,并提供复制和故障转移功能
节点
一个Redis集群通常由多个节点Node组成,节点与节点之间通过握手(CLUSTER MEET)建立连接
127.0.0.1:7000>cluster meet 127.0.0.1:7001
槽指派
Redis集群通过分片的方式来保存数据库中的键值对:集群的整个数据库被分为16384个槽,数据库中的每个键都属于这16384个槽中的其中一个,集群中的每个节点都可以处理0个或者最多16384个槽
ps:为什么需要16384个槽,redis采用的哈希算法(crc)产生了16位的数,为什么不是65536个槽?
原因在于redis集群节点之间需要定期发送心跳包,心跳包包括槽位信息,如果是65536个槽需要65536/8=8K字节的大小,而16384个槽需要2K字节的大小,综合考虑redis采用了16384个槽
只有所有的槽都有节点在处理时,集群叫做上线(ok)状态否则叫做下线(fail)状态。
每个节点会将自己的slots(记录了自己的槽指派信息)发送给其他节点,以此来告知对方自己负责哪些槽,同时节点也会记录集群中其他节点的slots信息
当客户端向节点发送与数据库键有关的命令时,节点会先判断该键属于哪个槽,该槽由哪个节点处理,如果由自己处理则会直接执行这个命令,否则会返回MOVED错误指引客户端转向正确的节点,并在此发送想要执行的命令。
需要注意的是集群模式的redis-cli客户端在接收到MOVED错误后,并不会打印MOVED错误,而是根据MOVED错误自动进行节点转向,并打印节点转向信息。
如何计算键属于哪个槽?
CRC16(key) & 16384 ,该方法表示先计算key的CRC-16校验和,在把它映射到0-16383之间
重新分片
Redis集群重新分片操作可以将任意数量已经指派给某个节点的槽,分配给另一个节点,且这个操作可以在线进行,集群不需要下线
迁移工作,可以使用redis-trib管理软件进行迁移,具体原理如下:
1、对目标节点,即是D节点发送cluster setslot import 命令,让目标节点做好准备接收迁移准备。
2、对源节点,即是C节点,发送cluster setslot migrating命令,让源节点做好准备迁移准备。
3、对源节点,发送cluster getkeysinslot
4、对于步骤3中获取的key,向源节点发送命令migrate
5、重复上述3,4步骤,直到所有key都迁移成功
在分片过程中,如果客户端向源节点发送一个跟数据库键有关的命令,而这个键已经被迁移到了目标节点,源节点会返回一个ASK错误,指引客户端跳转到目标节点中,同MOVED错误一样,该ASK错误也是被隐藏的
ASK错误和MOVED错误:
复制和故障转移
节点之间会定期发送PING包来检测对方是否在线,如果发现对方节点故障,则节点会发送消息给其他节点,但半数节点都认为该节点故障,则会真正认为该节点故障
当主节点发生故障后,会进行故障转移,在从节点中选举出新的主节点,选举过程和选举领头Sentinel的过程类似:
丛节点发现主节点故障后,会向集群广播这个消息,收到消息且具有投票权(正在负责处理槽)主节点会投票个这个从节点(每个主节点只能支持它最先收到的那个从节点),当从节点收到半数以上投票时当选主节点