redis集群是redis提供的分布式数据库方案,集群通过分片进行数据共享。
槽指派
一个redis集群由多个节点组成,集群通过分片的方式保存数据的键值对,集群的整个数据库被分为16384个槽(slot),当数据库的所有的槽都有节点在处理的时候,集群处于上线状态,否则,只要有任何一个槽没有得到处理,那么认为集群处于下线状态。比如一个集群中有三个节点A,B,C,通过向节点发送cluster addSlots命令,可以将一个或者对多个槽指派给节点负责。
一个节点除了会将自己负责处理的槽记录之外,还会告知群中其他节点自己处理的槽,因此集群中的每个节点都会知道数据库的槽分别指派给了那个节点。
当客户端发送执行命令的时候,接受命令的节点会计算出命令要处理的是哪一个槽,并检查这个槽是否分配给了自己,如果当前节点正好处理这个槽,那么节点就会执行这个命令,否则,向客户端返回一个moved错误,并告知正确的节点。
重新分片
可以将任意数量已经指派的某个节点的槽改为其他节点负责。并将相关槽的key-value从原节点转移到新的节点中。在处理的过程中,新旧节点都可以执行命令。
实现原理:
- 对目标节点发送命令,让目标节点准备好从原节点导入属于槽的键值对
- 源节点准备好将属于迁移槽的键值对迁移至目标节点
- 向源节点发送命令,获得属于源节点的槽的键值对的key
- 对于步骤3中获得的key,迁移至新的节点中
- 重复步骤3和4,直到源节点的槽中的所有节点都被迁移到目标节点
- 向集群中的任意节点发送命令,将指定的slot迁移至新的节点中,最终集群中的所有节点知道slot已经分配给新的节点
在重写指派的过程中,客户端向源节点发送命令,并且命令执行的key正好在要迁移的槽中的时候,:
- 源节点首先会在自己的数据库中寻找,找到的话,就直接执行命令
- 否则,key可能已经迁移到了新的节点中了,那么源节点引导客户端转向正在导入槽的节点,并在此发送要执行的命令