redis集群由多个节点组成组成,可以使用 cluster meet
握手成功,将节点添加到集群当中。每个node都有一个iclusterstate来存储集群中其他节点是信息。
(—)
例子:集群中有3台机器A,B,C
A跟D握手过程:
1、当A收到D的请求会为D建一个clusterNode结构 ,并将结构加到clusterState.nodes字典里.
2、A像D发送meet消息
3、D收到消息,建立一个clusterNode结构,添加到clusterState.nodes字典
4、D向A发送PONG消息
5、A接到消息向D发送PING消息,确认了D收到了meet消息
7、D收到PING消息,握手完成。
接下来由A通过gossip协议传播给其他节点,让其与D握手,最终所有节点握手完成。
(二)槽指派
1、记录node的槽:redis通过分片的方式来存储键值对,集群中一共有16384个槽,数据库中每个数据都存储在这些的槽中。,当集群中16384个槽都在处理时候集群处于上线ok的状态。
否则处于下线状态。在(一)中虽然集群已经连接,但是真个集群状态还是下线状态,通过cluster addslots可以向node添加处理的槽。
当16384个槽都分配完了,集群处于上线状态。槽的信息存储在clusterNode的solts属性中。
2、槽传播
各个节点会通过消息,来告知其他节点自己处理的槽,各个节点就存储了其他节点的槽信息。
当请求命令过来时候,接收节点会计算出命令处理的数据库属于哪个槽,并检查是否属于自己处理的槽,如果不是自己处理的,节点向客户端返回moved错误,指引客户端转向正确的节点,再次发送命令。
3、槽计算
CRC16(key) &16383
CRC16(key)算法计算crc16的校验和&16383计算出0~16383之间的整数作为key的槽号
4、集群中的节点只能使用0库,不能像单机中使用切换库
(三)重新分片
集群可以重新分配任意数量的solt是到其他节点,并且将solts相关的数据也移到其他节点,在重新分配过程中原节点和目标节点都可以继续处理命令请求。
重新分片实现原理
集群重新分片由redis-trib负责执行,通过向原节点和目标节点按发送命令进行重分操作。
分片步骤
1、redis-trib对目标节点发送cluster setslot
2、redis-trib对源几点发送cluster setslot
3、redis-trib向源节点发送 cluster getkeysinslot
4、对于3 trib想源节点发送 cluster migrate
5、trib会想集群中的任意一个节点发送cluster setslot
当重新分片期间,会发生slot的值一部分在源节点一部分在目标节点,在接收到命令时候,源节点会现在自己的库里找,找到就执行命令。否则返回一个ask错误,指引客户端想目标节点再次发送请求执行命令。
(四)
复制与故障转移
redis集群中的节点分为主节点和从节点,主节点用于处理槽,从节点用与复制主节点,当主节点下线时候从节点接管。
集群中的每个节点都会定期向集群中的其他节点发送ping消息,如果在规定的时间内没有返回pong消息,那么节点将目标几点标注为疑似下线,在clusterNode结构中将flags属性标注为redis_node_pfail标识。集群中所有节点通过相互发送消息的方式来交换各个节点的状态信息。当集群中半数以上的主节点将一个节点标识未下线,那么此节点将被下线。
当一个从节点在负责主节点时候发现主节点已经下线。从节点开始归主节点故障转移
转移过程
1、从节点会有一个节点成为主节点
2、新的主节点撤销对已有slot的指派,将这些slot归自己处理
3、像集群广播pong消息,让所有节点知道,这个节点已经是新的主节点
4、新节点开始处理集群命令,故障转移完成
选举新节点规则
1、集群中每一次故障集群的配置纪元都会被减一
2、对于配置纪元,每个主节点都有投票的机会,而第一个想主节点要求投票的从节点将获得主节点的投票
3、当从节点发现主节点已经下线,会想集群中广播一条消息,要求收到消息的其他节点想它投票
4、如果主节点想其投票,那边发送一条ack消息,表示支持
5、每个参与的从节点都会收到,主节点ack相应
6、当收到 N/2+1支持的时候,从节点变为主节点