概述
Redis集群是Redis提供的分布式数据库方案,集群通过分片(sharding)来进行数据共享,并提供复制和故障转移功能
节点
一个Redis集群通常由多个节点组成,在刚开始的时候,每个节点都是相互独立的,它们都处于一个只包含自己的集群当众,要组建一个真正可工作的集群,我们必须将各个独立的节点连接起来,构成一个包含多个节点的集群.
节点数据结构
clusterNode结构保存了一个节点的当前状态,比如节点的创建时间,节点的名字,节点当前的配置纪元,节点的IP地址和端口号等等
每个节点都会保存自己和集群中所有其他节点的状态
CLUSTER MEET命令的实现
CLUSTER MEET命令可以让节点A将另一个节点B添加到节点A当前所在的集群里面
- 节点A会为节点B创建一个clusterNode结构
- 节点A根据给定的IP和端口号向节点B发送一个MEET消息
- 节点B接收到节点A发送的MEET消息,节点B为节点A创建一个clusterNode结构
- 节点B向节点A返回一条PONG消息
- 节点A收到这条PONG消息,通过这条PONG消息节点A可以指导节点B已经成功地接收到了自己发送的MEET消息
- 节点A向节点B返回一条PING消息
- 节点B接收到节点A返回的PING消息,通过这条PING消息节点B可以指导节点A已经成功地接收到自己返回的PONG消息,握手完成
槽指派
Redis集群通过分片的方式来保存数据库中的键值对:集群的整个数据库被分为16384个槽,数据库中的每个键都属于这16384个槽的其中一个,集群中的每个节点可以处理0或最多16384个槽
当数据库中的16384个槽都有节点在处理时,集群处于上线状态;相反地,如果数据库中有任何一个槽没有得到处理,那么集群处于下线状态
执行完CLUSTER MEET命令后的集群还是下线状态,通过向节点发送CLUSTER ADDSLOTS命令可以将槽指派给节点负责
记录节点的槽指派信息
记录在clusterNode结构的slots属性和numslot属性
传播节点的槽指派信息
在集群中执行命令
当客户端向节点发送与数据库键有关的命令时,接受命令的节点会计算出命令要处理的数据库键属于哪个槽,并检查这个槽是都指派给了自己
计算键属于哪个槽
类似HashMap
1 | def slot_number(key): |
重新分片
重新分片不需要下线集群
重新分片的实现原理
重新分片操作是由Redis的集群管理软件redis-trib负责执行的,Redis提供了进行重新分片所需的命令,而redis-trib则通过向源节点和目标节点发送命令来进行重新分片操作
- redis-trib对目标节点发送CLUSTER SETSLOT
IMPORTING <source_id>命令,让目标节点准备好从源节点导入属于槽slot的键值对 - redis-trib对源节点发送CLUSTER SETSLOT
MIGRATING <target_id>命令,让源节点准备好属于槽slot的键值对迁移至目标节点 - redis-trib向源节点发送CLUSTER GETKEYSINSLOT
命令,获得最多count个属于slot的键值对的键名 - 对于步骤3的每个键名,redis-trib都向源节点发送一个MIGRATE <target_ip> <target_port> <key_name> 0
命令,将被选中的键原子地从源节点迁移至目标节点 - 重复执行步骤3和4,直到源节点保存的所有槽slot的键值对都被迁移至目标节点为止
- redis-trib向集群中的任意一个节点发送CLUSTER SETSLOT
NODE <target_id>命令,将槽slot指派给目标节点,这一指派信息会通过消息发送至整个集群,最终集群中的所有节点都会知道槽slot已经指派给了目标节点
ASK错误
TODO