Redis 集群
Redis 集群
集群是 Redis 提供的分布式数据库的方案,集群通过分片来进行数据共享、并提供了复制和故障转移功能。
1 节点
Redis 集群 将多个独立的节点连接起来构成一个包含多个节点的集群。
通过CLUSTER MEET <ip> <port>
命令可以将另外一个节点加入到当前节点所在的集群。
1.1 启动节点
在启动过程中 Redis 服务器会根据 cluster-enable
配置决定是否开启集群模式。

1.2 数据结构
通过 clusterNode
结构保存了一个节点的当前状态:创建时间、节点的名字、配置济源、IP地址、端口号等信息。每个节点都会为所有节点创建一个 clusterNode
记录所有节点的状态。
每个节点同时保存着一个 clusterState
结构,记录了当前节点的视角下集群目前的状态。
2 槽指派
集群的整个数据库被划分成 16384 个槽,每个键都属于这些槽中的一个。
在 clusterNode
中定义了 slots
数据,通过一个二进制数组描述哪些槽是节点负责处理的。取出和设置 slots
数组中的任意一个二进制位的复杂度仅为 O(1),所以对于一个给定节点的slots数组来说,检查是否负责处理槽和将槽指派给其他节点负责的时间复杂度都是 O(1)。
节点之间会互相发送自己的 slots
数组信息,告诉其他节点自己目前负责处理的槽。
同时定义了 clusterState
结构记录了每个槽对应的指派信息(指向clusterNode的指针)。

3 集群中执行命令
3.1 流程
- 接收命令的节点收到命令。
- 判断要出里的键属于哪个槽,是否指向了自己。
- 如果指向了自己则执行这个命令。
- 否则返回一个
MOVED
错误,指向可能端转向正确的节点,再次发送之前想要的命令。
4 数据库实现
节点使用 slots_to_key
跳跃表来保存槽和键之间的关系,对于跳跃表每个节点的分值都是一个槽,成员都是一个数据库键。

5 分片
支持在线重分片,在重新分片过程中,集群不需要下线,并且源节点和目标节点都可以处理命令请求。
5.1 原理

5.2 迁移过程中
在 clusterState
中定义个 importing_slots_from
数据记录了当前节点正在从其他节点导入的槽, migrating_slots_to
数组记录了当前节点正在迁移至其他节点的槽。
在迁移过程中,如果源节点收到已经被迁移的 key
,会返回 ask
错误和 IP 地址端口号,会先向目标节点发送asking
命令,然后再次执行命令。
asking
标识只会生效一次,ask
错误只是两个节点在迁移槽过程中中使用的一种临时措施。

6 复制和故障转义
Redis 集群的节点分为主节点和从节点,主节点用于处理槽、从节点用于复制某个主节点,当主节点下线时,代替成为新的主节点。
6.1 故障发现
集群中的每个节点都会定期的向集群中的其他节点发送PING消息,以此来检测对方是否在线,如果执行时间没有返回 PONG
消息,则叫节点标记位 疑似下线状态 probable fail,如果一个集群里面,半数以上负责处理槽的主节点都将某个主节点x标记为疑似下线,那么这个主节点x将被标记为已下线状态,同时广播出去。
6.2 故障转移
- 复制下线主节点的所有从节点里面,选择一个从节点。
- 选中的从节点执行
slaveof no one
命令,成为新的主节点。 - 新的主节点会撤销所有对已下线主节点槽指派,并将这些指派给自己。
- 广播一条消息,告诉其余节点当前节点已经变成了主节点。
- 新的节点开始接受和处理请求。
6.3 选举
也是通过 raft
算法选举出 leader
。