Redis集群-槽指派
Redis集群通过分片的方式来保存数据库中的键值对:集群的整个数据库被分成16384个槽。
当数据库中的16384个槽都有节点在处理时,集群处于上线状态。相反,数据库中有任何一个槽没有得到处理,那么集群处于下线状态。
通过向节点发送CLUSTER ADDSLOTS命令,我们可以将一个或多个槽指派给节点负责:
CLUSTER ADDSLOTS <slot> [slot...]
将槽0至槽5000指派给节点7000负责:
127.0.0.1:7000> CLUSTER ADDSLOTS 0 1 2 3 4 ... 5000
记录节点的槽指派信息
clusterNode结构的slots 属性和numslot 属性记录了节点负责处理哪些槽:
image.png
slots是一个二进制数组,数组的长度16384/8=2048个字节。
如果slots数组在索引i上的二进制位的值为1,那么表示节点负责处理槽i。
如果slots 数组在索引i上的二进制位的值为0,那么表示节点不负责处理槽i。
下图展示了一个slots数组示例∶这个数组索引0至索引7上的二进制位的值都为1,其余所有二进制位的值都为0,这表示节点负责处理槽0至槽7。
image.png
传播节点的槽指派信息
一个节点除了记录自己负责处理的槽,它还会将自己的slots数组通过消息发送给集群中的其他节点,向其他节点告知自己目前处理哪些槽。
image.png
ClutserState和ClusterNode的关系
当节点A通过消息从节点B那里接收到节点B的slots数组时,节点A会在自己的clusterState.nodes字典中查找节点B对应的clusterNode结构,并对结构中的slots数组进行保存或者更新。所以集群中的每个节点都会知道数据库中的16384个槽分别被指派给了集群中的哪些节点。
ClutserState和ClusterNode的关系如下:
image.png
通过这种结构,需要知道槽2被指派给了哪个节点,那么只要访问数组项slots[2],就可以马上知道槽2被指派给了哪个节点。
已经使用ClutserState记录了slots,为什么ClusterNode还要记录?
因为当程序需要将某个节点的槽指派信息通过消息发送给其他节点时,程序只需要将相应节点的clusterNode.slots数组整个发送出去就可以了。 不需要再去ClutserState里面查看自己处理哪些槽。
另一方面,如果Redis不使用clusterNode.slots数组,而单独使用clusterState.slots 数组的话,那么每次要将节点A的槽指派信息传播给其他节点时,程序必须先遍历整个clusterState.slots数组,记录节点A负责处理哪些槽,然后才能发送节点A的槽指派信息,这比直接发送clusterNode. slots 数组要麻烦和低效得多。