跳至主要內容

Redis 集群

blacklad大约 4 分钟RedisRedisRedis 设计与实现

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 流程

  1. 接收命令的节点收到命令。
  2. 判断要出里的键属于哪个槽,是否指向了自己。
  3. 如果指向了自己则执行这个命令。
  4. 否则返回一个 MOVED 错误,指向可能端转向正确的节点,再次发送之前想要的命令。

4 数据库实现

节点使用 slots_to_key 跳跃表来保存槽和键之间的关系,对于跳跃表每个节点的分值都是一个槽,成员都是一个数据库键。

image-20210823212452208
image-20210823212452208

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 故障转移

  1. 复制下线主节点的所有从节点里面,选择一个从节点。
  2. 选中的从节点执行 slaveof no one 命令,成为新的主节点。
  3. 新的主节点会撤销所有对已下线主节点槽指派,并将这些指派给自己。
  4. 广播一条消息,告诉其余节点当前节点已经变成了主节点。
  5. 新的节点开始接受和处理请求。

6.3 选举

也是通过 raft 算法选举出 leader

上次编辑于:
贡献者: blacklad