Redis-集群

概述

Redis集群是Redis提供的分布式数据库方案,集群通过分片(sharding)来进行数据共享,并提供复制和故障转移功能

节点

一个Redis集群通常由多个节点组成,在刚开始的时候,每个节点都是相互独立的,它们都处于一个只包含自己的集群当众,要组建一个真正可工作的集群,我们必须将各个独立的节点连接起来,构成一个包含多个节点的集群.

节点数据结构

clusterNode结构保存了一个节点的当前状态,比如节点的创建时间,节点的名字,节点当前的配置纪元,节点的IP地址和端口号等等

每个节点都会保存自己和集群中所有其他节点的状态

CLUSTER MEET命令的实现

CLUSTER MEET命令可以让节点A将另一个节点B添加到节点A当前所在的集群里面

  1. 节点A会为节点B创建一个clusterNode结构
  2. 节点A根据给定的IP和端口号向节点B发送一个MEET消息
  3. 节点B接收到节点A发送的MEET消息,节点B为节点A创建一个clusterNode结构
  4. 节点B向节点A返回一条PONG消息
  5. 节点A收到这条PONG消息,通过这条PONG消息节点A可以指导节点B已经成功地接收到了自己发送的MEET消息
  6. 节点A向节点B返回一条PING消息
  7. 节点B接收到节点A返回的PING消息,通过这条PING消息节点B可以指导节点A已经成功地接收到自己返回的PONG消息,握手完成

槽指派

Redis集群通过分片的方式来保存数据库中的键值对:集群的整个数据库被分为16384个槽,数据库中的每个键都属于这16384个槽的其中一个,集群中的每个节点可以处理0或最多16384个槽

当数据库中的16384个槽都有节点在处理时,集群处于上线状态;相反地,如果数据库中有任何一个草没有得到处理,那么集群处于下线状态

执行完CLUSTER MEET命令后的集群还是下线状态,通过向节点发送CLUSTER ADDSLOTS命令可以将槽指派给节点负责

记录节点的槽指派信息

记录在clusterNode结构的slots属性和numslot属性

传播节点的槽指派信息

在集群中执行命令

当客户端向节点发送与数据库键有关的命令时,接受命令的节点会计算出命令要处理的数据库键属于哪个槽,并检查这个槽是都指派给了自己

计算键属于哪个槽

类似HashMap

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

重新分片

重新分片不需要下线集群

重新分片的实现原理

重新分片操作是由Redis的集群管理软件redis-trib负责执行的,Redis提供了进行重新分片所需的命令,而redis-trib则通过向源节点和目标节点发送命令来进行重新分片操作

  1. redis-trib对目标节点发送CLUSTER SETSLOT IMPORTING <source_id>命令,让目标节点准备好从源节点导入属于槽slot的键值对
  2. redis-trib对源节点发送CLUSTER SETSLOT MIGRATING <target_id>命令,让源节点准备好属于槽slot的键值对迁移至目标节点
  3. redis-trib向源节点发送CLUSTER GETKEYSINSLOT 命令,获得最多count个属于slot的键值对的键名
  4. 对于步骤3的每个键名,redis-trib都向源节点发送一个MIGRATE <target_ip> <target_port> <key_name> 0 命令,将被选中的键原子地从源节点迁移至目标节点
  5. 重复执行步骤3和4,直到源节点保存的所有槽slot的键值对都被迁移至目标节点为止
  6. redis-trib向集群中的任意一个节点发送CLUSTER SETSLOT NODE <target_id>命令,将槽slot指派给目标节点,这一指派信息会通过消息发送至整个集群,最终集群中的所有节点都会知道槽slot已经指派给了目标节点

ASK错误

TODO

复制与故障转移