Redis Cluster执行流程

Redis Cluster执行流程

集群(cluster)是Redis提供的分布式数据库解决方案,集群通过分片(sharding)来进行数据共享,并提供数据复制(replication)和故障转移(failover)等功能。下面介绍下Cluster的执行流程。

一. 启动节点

Redis服务器在启动时,会根据cluster-enabled配置决定是否开启服务器的集群模式。如果未开启,就进入stand alone模式,以普通单机Redis方式运行。否则进入集群模式。

一个Redis集群通常由多个节点(node)组成。在初始化时,每个node都是相互独立的,它们都处于一个只包含自己的集群当中。要想组成一个真正可用的集群,必须将多个独立的节点连接起来。

向一个node发送CLUSTER MEET命令,可以让node与指定的节点进行握手,握手成功后,指定的节点就加入到node所在的集群中。

新的节点加入集群后。node会通过Gossip协议传播给集群中的其他节点,让其他节点也与新加入的节点握手。最终经过一段时间后,集群中的所有节点就建立起了连接。

二. 槽指派

**Redis通过数据分片的方式保存数据库中的键值对:整个数据库被分为16384个槽(slot),数据库中的每个键都位于这16384个槽中的一个,集群中的每个节点都可以处理0~16384个槽。**可以通过命令为每个节点分配指定的槽位。

三. 在集群中执行命令

在对数据库中的16384个槽都分配成功了之后,集群就进入上线状态,就可以正常接收客户端命令提供服务了。

当客户端向集群中的节点发送key相关操作的命令时,接收命令的节点会进行如下操作:

  1. 计算key属于哪个槽。Redis通过:CRC16(key) % 16383 算法计算出key属于哪个槽位。
  2. 如果目标槽位正好指派给了当前节点,那么当前节点直接执行这个命令。
  3. 目标槽位在其他节点上,那么当前节点会向客户端返回一个MOVED错误,引导客户端重定向(redirect)到正确的节点上,并再次发送想要执行的命令。

四. 重新分片

Redis集群可以通过重新分片操作,将任意数量的已经指派给某个节点(源节点)的槽改为指派给另一个节点(目标节点),并且槽位上所属的所有键值对也会一并被移动过去。

重新分片操作可以在线执行,在重新分片操作执行过程中,集群不需要下线,并且源节点和目标节点都可以继续处理客户端请求。

五. ASK错误

在执行重新分片的过程中,可能存在这样一种情况:在迁移某个槽位上的数据时,一部分数据已经被迁移到了目标节点,而还有一部分数据仍然在源节点上未迁移完成。此时客户端如果向源节点发送请求,要对这个槽位上的数据进行处理,则会进行如下的操作:

  1. 源节点首先会在自己的数据库中查找指定的key,如果找到了,则直接在源节点上执行客户端命令。
  2. 如果未找到,则该key很有可能已经被迁移到了目标节点,此时源节点会向目标节点返回一个ASK错误,指引客户端转向正在导入槽的目标节点,并再次发送之前要执行的命令。

六. 复制与故障转移

集群中的节点分为主节点(master)和从节点(slave)。主节点用于处理槽相关的操作,而从节点则用于复制主节点,并在主节点下线时,选举出一个新的主节点,代替下线的主节点继续处理命令请求。

集群中的每个节点都会定期向集群中的其他节点发送PING消息,以此来检测对方的在线状态。如果接收PING消息的节点没有在规定时间内返回PONG响应,则发送PING消息的节点会将接收PONG消息的节点标记为疑似下线(probable fail, PFAIL)状态。

集群中的每个节点都会通过相互发送消息的方式,来交换集群中各个节点的状态信息,例如一个节点是在线状态、疑似下线状态(PFAIL)还是已下线状态(FAIL)。

如果一个集群中,半数以上的处理槽的主节点都认为一个主节点处于PFAIL状态,那么这个主节点就会被标记为已下线状态(FAIL),并将这个主节点下线的消息在集群中进行广播,所有接受到这条消息的节点都会立即将其标记为FAIL状态。

当一个从节点发现它复制的主节点进入下线状态时,那么从节点就会对已下线的主节点进行故障转移,下面是执行故障转移的步骤:

  1. 从下线的主节点的所有从节点中,选举一个出来。
  2. 被选中的从节点执行SLAVEOF no one命令,成为新的主节点。
  3. 新的主节点会撤销对已下线主节点的所有槽指派,并将这些槽全部指派给自己。
  4. 新的主节点向集群中广播一条PONG消息,其他节点接收到消息后会立即知道新主节点的产生,并且这个主节点已经接管了已下线主节点的所有槽。
  5. 新的主节点开始接收和自己负责的槽相关的所有命令,故障转移完成。

七. 消息

集群中的各个节点都是通过消息来彼此通信的。发送消息的节点成为sender,接收消息的节点成为receiver。节点的消息类型主要有一下五种:

  1. MEET:当sender接收到客户端发送的CLUSTER MEET命令时,会向receiver发送MEET消息,请求receiver加入到sender所在的集群中。
  2. PING:集群中的每个节点默认每秒钟从已知节点列表中随机选出5个节点,然后对这5个节点中最长时间没有发送PING消息的节点发送PING消息,以此来检测被选中的节点是否在线。此外,如果节点A最后一次收到节点B的PONG消息的时间,距离当前时间已经超过了节点A设置的cluster-node-timeout时间的一半,那么节点A也会向节点B发送PING消息,这样可以防止节点A由于长期没有选择节点B而导致对节点B的信息更新的滞后。
  3. PONG:当receiver收到sender发来的MEET或PING消息后,为了向sender确认这条消息已送达,receiver就会向sender响应一条PONG消息。另外,一个几点也可以通过向集群中广播PONG消息,来刷新其他节点对于该节点的认知。例如,当一次故障转移执行成功后,新的主节点就会向集群中广播一条PONG消息,通知其他节点自己变成的新的主节点,并且接管了原来主节点的所有槽。
  4. FAIL:当一个主节点A判断另一个主节点B已经进入下线状态时,A就会向集群中广播一条关于B的FAIL消息,所有收到这条消息的节点都会立即将节点B标记为已下线状态。
  5. PUBlISH:当一个节点接收到PUBLISH命令时,节点会执行这个命令,并向集群中广播一条PUBLISH消息,所有接受到这条PUBLISH消息的节点都会执行相同的PUBLISH命令。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章