Redis 切片集群模式

Redis主从模式和哨兵模式都实现了读负载均衡,但是依然存在单点故障和写操作无法均衡问题。Redis切片集群是部署多个主节点,每个主节点都有若干从节点,主节点之间地位平等,每个主节点存储部分数据。

哨兵集群 切片集群
image image

切片集群原生支持水平横向扩展,天然支持分布式,当集群现有节点无法支持数据存储或负载压力较大的时候,可以直接通过增加机器节点解决。切片集群的动态扩缩容是其最大的优势。

分片规则

Redis集群在初始化时会创建16384个哈希槽,并将这些哈希槽均匀分配给每个主节点,对于每一个key计算CRC-16校验码对16384取模即为存储该key的哈希槽。

为什么是16384呢?Redis节点之间通过Gossip协议进行通信,定期发送心跳包,心跳包包含了节点的元数据,如果哈希槽过多,心跳消息过大,网络通信效率差

集群扩缩容

当有新的主节点加入或主节点退出时,会触发集群的扩/缩容机制,要分配/收回变动节点的哈希槽,整个数据迁移过程属于平滑迁移,扩/缩容期间可以正常对外提供服务,过程如下:

  1. 标记源节点的迁移槽位为MIGRATING状态,目标节点的迁移槽位为IMPORTING状态
  2. 数据迁移,每个key的迁移是原子性的,MIGRATE命令实现

扩/缩容期间,集群可以正常响应客户端请求,如果请求的key对应的哈希槽正处于迁移期间,则发送临时重定向消息,如果已经迁移完成,发送永久重定向。

故障检测机制

Redis切片集群采用基于Gossip协议的故障检测机制,每个节点只会与集群中的若干节点通信,久而久之达到最终一致性的状态。

  1. 节点A会随机地向其他若干节点发送PING消息,如果限定时间内没有收到回复,标记节点B为主观下线
  2. 节点A通过Gossip协议,在它后续发送给其他节点的PING/PONG消息中,附带一条节点B主观下线地信息
  3. 其他节点收到后,会去主动判断节点B是否下线,并通过Gossip协议进行二次传播
  4. 当某一个主节点收到的PONG消息中,有超过半数的主节点达成共识,都认为节点B下线,标记为客观下线
  5. 首先达成共识的主节点向集群广播节点B下线,所有节点同步这条消息

注意!!只有主节点有投票权,超过半数的主节点认为下线才能标记为客观下线。从流程也可以看出,从主观下线到客观下线延迟很高,因为Gossip是一个局部协议,每次只会同步给若干节点,再由这些节点去同步其他节点。

graph TD A[节点A向节点B发送PING] --> B{在cluster-node-timeout内<br/>收到PONG回复?} B -- 是 --> C[通信正常,状态更新] B -- 否 --> D[节点A将节点B标记为<br/>主观下线PFAIL] D --> E[节点A通过Gossip协议<br/>向集群传播此信息] E --> F[其他主节点验证<br/>与节点B的连接状态] F --> G{超过半数的主节点<br/>同意节点B主观下线?} G -- 否 --> H[维持PFAIL状态,继续观察] G -- 是 --> I[节点B被标记为<br/>客观下线FAIL] I --> J[触发故障转移流程]

故障恢复机制

  1. 从节点收到自己的主节点下线的广播消息后,同步自身数据,标记主节点下线
  2. 从节点不会立刻开始选举,而是根据自身的复制偏移量计算一个延迟等待时间,复制偏移量越大,延迟时间越小(保证复制进度快的节点更快发起选举)
  3. 从节点延迟时间过后,纪元数+1,向其他主节点发送消息请求投票
  4. 所有主节点收到要求投票的消息后,会在该纪元内将选票投出,所以发起选举的时间越早,越容易获得选票
  5. 如果从节点在集群配置纪元内收到了超过半数主节点的同意票,它就赢得了选举,成为新的主节点,向集群广播消息,其他节点收到消息后,会更新自己的本地配置
flowchart TD A[主节点被标记为客观下线 FAIL] --> B[从节点发起选举<br>增加纪元并投票] B --> C{获得超过半数<br>主节点的投票?} C -- 是 --> D[赢得选举<br>从节点执行晋升操作] C -- 否 --> E[选举失败<br>等待超时后重新发起] D --> F[新主节点接管<br>原主节点的哈希槽] F --> G[新主节点广播<br>PONG消息通知集群] G --> H[更新集群配置<br>客户端重定向到新主节点] H --> I[恢复完成<br>集群恢复正常服务]
posted @ 2025-12-03 18:40  xxs不是小学生  阅读(2)  评论(0)    收藏  举报