redis集群 第二节 槽指派

2017-04-10  本文已影响0人  c84f3109853b

Redis集群通过分片的方式来保存数据库中的键值对:集群的整个数据库被分为16384个槽(slot),数据库中每个键都属于这16384个槽的其中一个,集群中的每个节点可以处理0个或最多16384个槽。
当数据库总的16384个槽都有节点在处理时,集群处于上线状态(ok);相反地,如果数据库中有任何一个槽没有得到处理,那么集群处于下线状态(fail)。
通过向节点发送CLUSTER ADDSLOTS命令,我们可以将一个或多个槽指派(assign)给节点负责:

CLUSTER ADDSLOTS <slot> [slot ...]

本节接下来的内容将首先介绍节点保存槽指派信息的方法,以及节点之间传播槽指派信息的方法,之后再介绍CLUSTER ADDSLOTS命令的实现。

2.1 记录节点的槽指派信息

clusterNode结构的slots属性和numslot属性记录了节点负责处理哪些槽:

struct clusterNode {
// ...
unsigned char slots[16384/8];
int numslots;
// ...
};

slots属性是一个二进制位数组(bit array),这个数组的长度为16384/8=2048个字节,共包含16384个二进制位。
Redis以0为起始索引,16383为终止索引,对slots数组中的16384个二进制位进行编号,并根据索引i上的二进制位的值来判断节点是否负责处理槽i:

至于numslots属性则记录节点负责处理的槽的数量,也即是slots数组中值为1的二进制位的数量。

2.2 传播节点的槽指派信息

一个节点除了会将自己负责处理的槽记录在clusterNode结构的slots属性和numslots属性之外,它还会将自己的slots数组通过消息发送给集群中的其他节点,以此来告知其他节点自己目前负责处理哪些槽。
当节点A通过消息从节点B那里接收到节点B的slots数组时,节点A会在自己的clusterState.nodes字典中查找节点B对应的clusterNode结构,并对结构中的slots数组进行保存或者更新。
因为集群中的每个节点都会将自己的slots数组通过消息发送给集群中的其他节点,并且每个接收到slots数组的节点都会将数组保存到相应节点的clusterNode结构里面,因此,集群中的每个节点都会知道数据库中的16384个槽分别被指派给了集群中的哪些节点。

2.3 记录集群所有槽的指派信息

clusterState结构中的slots数组记录了集群中所有16384个槽的指派信息:
typedef struct clusterState {
// ...
clusterNode *slots[16384];
// ...
} clusterState;
slots数组包含了16384个项,每个数组项都是一个指向clusterNode结构的指针:

如果只将槽指派信息保存在各个节点的clusterNode.slots数组里,会出现一些无法高效地解决的问题,而clusterState.slots数组的存在解决了这些问题:

要说明的一点是,虽然clusterState.slots数组中记录了集群中所有槽的指派信息,但使用clusterNode结构的slots数组来记录单个节点的槽指派信息仍然是有必要的:

2.4 CLUSTER ADDSLOTS命令的实现

CLUSTER ADDSLOTS命令接受一个或多个槽作为参数,并将所有输入的槽指派给接收该命令的节点负责:

CLUSTER ADDSLOTS <slot> [slot ...]

CLUSTER ADDSLOTS命令的实现可以用以下伪代码来表示:

def CLUSTER_ADDSLOTS(*all_input_slots):
# 遍历所有输入槽,检查它们是否都是未指派槽
for i in all_input_slots:
# 如果有哪怕一个槽已经被指派给了某个节点
# 那么向客户端返回错误,并终止命令执行
if clusterState.slots[i] != NULL:
reply_error()
return
# 如果所有输入槽都是未指派槽
# 那么再次遍历所有输入槽,将这些槽指派给当前节点
for i in all_input_slots:
# 设置clusterState结构的slots数组
# 将slots[i]的指针指向代表当前节点的clusterNode结构
clusterState.slots[i] = clusterState.myself
# 访问代表当前节点的clusterNode结构的slots数组
# 将数组在索引i上的二进制位设置为1
setSlotBit(clusterState.myself.slots, i)

上一篇下一篇

猜你喜欢

热点阅读