【Redis】Redis集群架构剖析(3):集群处理redis-cli指令

  在前两篇Redis集群架构剖析中,我们创建了一个集群,并且把这个集群由下线状态启动为上线状态。集群上线之后,就表示我们可以向集群的节点发送数据命令了。在开始之前,依旧可以先思考下面的问题:

  • 节点如何找到要处理的数据(这个其实在上一篇有提到)?
  • 如果不是该节点处理的数据,节点会怎么做?

  针对上面的问题,结合前两篇的内容,大致可以猜一下流程可以是,先找到对应的key的槽位在哪?是不是我发送到的节点上面处理的,如果是的话就执行,不是的话可能就转给负责这个槽位的节点。无论是读和写,都需要找到槽位对应的节点。下面具体介绍一下的集群处理指令时的操作

大体流程

【Redis】Redis集群架构剖析(3):集群处理redis-cli指令_第1张图片

  从上图可以看到和我们预想的差不多:

  1. redis-cli向节点发送数据库命令
  2. 收到命令的节点计算建属于哪个槽,然后判断是否在本节点
  3. 如果在本节点,则执行命令
  4. 如果不在本节点,会返回一个MOVED错误给redis-cli,然后客户端会根据MOVED提供的信息转向正确的节点

  举个例子,6370要执行两个指令(槽位我是乱写的):

127.0.0.1:6370 > GET i
"200" #在当前节点直接执行

127.0.0.1:6370 > SET new 100
-> Redirected to slot [15045] located at 127.0.0.1:6371
OK

127.0.0.1:6371 > GET new
100

  这里面的三个重点:

  • 节点如何计算键对应的槽位
  • 节点如何找到槽位对应的节点
  • MOVED错误是什么?包含什么消息?执行了什么?

key属于哪个槽

  节点使用下面这个算法来计算键对应的槽位:

def slot_number(key):
	return CRC16(key) & 16383

  CRC16(key)语句用与计算key的CRC-16校验和,而&16383适用于算出一个介于0 ~ 16383之间的证书作为key的槽位:

127.0.0.1:6370 > CLUSTER KEYSLOT "Im"
(integer) 2655

127.0.0.1:6370 > CLUSTER KEYSLOT "best"
(integer) 10040

  KEYSLOT的伪代码如下

def CLUSTER_KEYSLOT(key):
	// 计算槽位
	slot = slot_number(key)
    
   	// 将槽位返回给客户端
    reply_client(slot)

slot属于哪个节点

  当节点计算出key多数的slot之后,节点就会检查自己的clusterState.slots数组中的index i,判断key所在的slot是否由自己负责:

  • 如果clusterState.slots[i]等于clusterState.myself,就表示slot i由当前节点负责,节点可以直接执行客户端发送的命令
  • 如果不是,而是其他的clusterNode,节点会根据指向的clusterNode结构所记录的节点的IP和PORT,向客户端发送MOVED错误,指引客户端转向至正确处理该slot的节点。

  如下图,slot 2655指向的就是myself节点,当前节点直接执行即可。slot 15045是另外的节点,所以需要返回给客户端MOVED错误。

【Redis】Redis集群架构剖析(3):集群处理redis-cli指令_第2张图片

MOVED错误

  当节点发现键所在槽并非由自己负责处理的时候,节点就会向客户端返回一个MOVED错误,指引客户端转向至正在负责该slot的节点。

  下面为MOVED的格式

#  : key所在slot
# : 负责处理slot的节点的IP和PORT
MOVED <slot> <ip>:<port>

MOVED 15045 127.0.0.1:6371

  当客户端接收到节点返回的MOVED的错误时,客户端会根据MOVED错误中的IP和PORT,转向至负责处理改slot的节点,并向该节点重新发送之前想要执行的命令。

  以上面redirect的例子为例:

127.0.0.1:6370 > SET new 100
-> Redirected to slot [15045] located at 127.0.0.1:6371
OK

【Redis】Redis集群架构剖析(3):集群处理redis-cli指令_第3张图片

  一个集群客户端通常与集群终端额多个几点创建套接字连接,而所谓的节点转向实际上就是换一个套接字来发送命令。

  MOVED错误一般在集群模式下会被隐藏,而是向上面的例子,直接转向到对应的节点。如果想要查看这个错误的话,需要使用单机模式进入,也就是redis-cli的时候不要带-c,那么以上面的例子来说就会返回

(error) MOVED 15045 127.0.0.1:6371

  注意,单机和集群模式下的数据库方面有一个区别是,集群节点只能使用0号数据库,而不是向单机那样0-15


  这篇文档,我们了解了集群是如何处理由客户端发过来的指令的,再结合一下前两篇的数据结构,就会很容易理解。这篇文档的场景是普遍场景,就好比写代码时自己测试一点问题都没有,但是如果节点发生槽转移呢,或者重新分配槽呢?针对这个一个异常行为,我们下节分析。


系列文章:

  1. 【Redis】Redis集群架构剖析(1):认识cluster
  2. 【Redis】Redis集群架构剖析(2):槽位
  3. 【Redis】Redis集群架构剖析(4):槽位迁移,重新分配
  4. 【Redis】Redis集群架构剖析(5):复制与故障转移

你可能感兴趣的:(redis,redis,架构,redis-cluster,分布式)