分布式复述,深度历险集群

  

本文为分布式复述,深度历险系列的第三篇,主要内容为复述的集群,也就是复述,集群功能。

复述,集群是复述,官方提供的分布式方案,整个集群通过将所有数据分成16384个槽来进行数据共享。

集群基础实现

一个集群由多个复述,节点组成,不同的节点通过<代码>集群满足命令进行连接:

<代码>集群满足& lt; ip>& lt; port>

收到命令的节点会与命令中指定的目标节点进行握的手,握手成功后目标节点会加入到集群中,看个例子,图片来自于复述的设计与实现:

分布式复述,深度历险集群

分布式复述,深度历险集群

分布式复述,深度历险集群

分布式复述,深度历险集群

分布式复述,深度历险集群

槽分配

一个集群的所有数据被分为16384个槽,可以通过集群ADDSLOTS <代码> 命令将槽指派给对应的节点。当所有的槽都有节点负责时,集群处于上线状态,否则处于下线状态不对外提供服务。

clusterNode的位数组插槽代表一个节点负责的槽信息。

 struct clusterNode {
  
  
  无符号字符的位置(16384/8);/*槽由这个节点*/int numslots;/*槽数由这个节点*/?
  }

看个例子,下图中1,3,5,8,9,10位的值为1,代表该节点负责槽1,3,5,8,9,10 .

每个复述,服务器上都有一个ClusterState的对象,代表了该服务器所在集群的信息,其中字段槽记录了集群中所有节点负责的槽信息。

 typedef struct ClusterState {//负责处理各个槽的节点//例如槽[我]=clusterNode_A表示槽我由节点一处理//槽[我]=零代表该槽目前没有节点负责
  clusterNode *插槽(REDIS_CLUSTER_SLOTS);
  
  }

槽重分配

可以通过redis-trib工具对槽重新分配,重分配的实现步骤如下:

<李>

通知目标节点准备好接收槽

<李>

通知源节点准备好发送槽

<李>

向源节点发送命令:<代码>集群GETKEYSINSLOT & lt; slot>& lt; count> 从源节点获取最多算个槽槽的关键

<李>

对于步骤3的每个键,都向源节点发送一个<代码> & lt;迁移target_ip>& lt; target_port>& lt; key_name>0 & lt; timeout>命令,将被选中的键原子的从源节点迁移至目标节点。

<李>

重复步骤3,4。直到槽槽的所有键值对都被迁移到目标节点

<李>

将槽槽指派给目标节点的信息发送到整个集群。

在槽重分配的过程中,槽中的一部分数据保存着源节点,另一部分保存在目标节点。这时如果要客户端向源节点发送一个命令,且相关数据在一个正在迁移槽中,源节点处理步骤如图:
分布式复述,深度历险集群

当客户端收到一个问错误的时候,会根据返回的信息向目标节点重新发起一次请求。

问和移动的区别主要是问是一次性的,感动是永久性的,有点像Http协议中301和302的。

一次命令执行过程

我们来集群下看一次命令的请求过程,假设执行命令<代码>得到testKey

<李>

集群客户端在运行前需要配置若干个服务器节点的ip和端口。我们称这些节点为种子节点。

<李>

集群的客户端在执行命令时,会先通过计算得到关键的槽信息,计算规则为:<代码> getCRC16(关键),(16384 - 1)> <李>

向种子节点发送槽<代码> 命令以获得整个集群的槽分布信息,然后跳转到第2步重试命令

<李>

向负责该槽的服务器发起调用
服务器处理如图:
分布式复述,深度历险集群

<李>

客户端如果收到搬错误,则根据对应的地址跳转到第4步重新请求,

<李>

客户段如果收到问错误,则根据对应的地址跳转到第4步重新请求,并在请求前带上问标识。

分布式复述,深度历险集群