Redis Cluster 实现

本文将从设计思路,功能实现,源码几个方面介绍Redis Cluster。假设读者已经了解Redis Cluster的使用方式。

简介

Redis Cluster作为Redis的分布式实现,主要做了两个方面的事情:

1,数据分片

2,故障恢复

设计思路

性能为第一目标

提高可用性

损失一致性

功能实现

1,数据分片

我们已经知道数据会按照key哈希到不同的slot,而每个节点仅负责一部分的slot,客户端根据slot将请求交给不同的节点。将slots划分给不同节点的过程称为数据分片,对应的还可以进行分片的重新分配。这部分功能依赖外部调用命令:

分片

再分配

再分配要做的是将一些slots从当前节点(source)迁移到其他节点(target)

2,请求重定向

由于每个节点只负责部分slot,以及slot可能从一个节点迁移到另一节点,造成客户端有可能会向错误的节点发起请求。因此需要有一种机制来对其进行发现和修正,这就是请求重定向。有两种不同的重定向场景:

1),MOVE

2),ASK

3),区别

区分这两种重定向的场景是非常有必要的:

3,状态检测及维护

Cluster中的每个节点都维护一份在自己看来当前整个集群的状态,主要包括:

当集群状态变化时,如新节点加入、slot迁移、节点宕机、slave提升为新Master,我们希望这些变化尽快的被发现,传播到整个集群的所有节点并达成一致。节点之间相互的心跳(PING,PONG,MEET)及其携带的数据是集群状态传播最主要的途径。

心跳时机:

Redis节点会记录其向每一个节点上一次发出ping和收到pong的时间,心跳发送时机与这两个值有关。通过下面的方式既能保证及时更新集群状态,又不至于使心跳数过多:

心跳数据

心跳处理

图1 新节点加入

注:Gossip的存在使得集群状态的改变可以更快的达到整个集群。每个心跳包中会包含多个Gossip包,那么多少个才是合适的呢,redis的选择是N/10,其中N是节点数,这样可以保证在PFAIL投票的过期时间内,节点可以收到80%机器关于失败节点的gossip,从而使其顺利进入FAIL状态。

广播

当需要发布一些非常重要需要立即送达的信息时,上述心跳加Gossip的方式就显得捉襟见肘了,这时就需要向所有集群内机器的广播信息,使用广播发的场景:

4,故障恢复(Failover)

当slave发现自己的master变为FAIL状态时,便尝试进行Failover,以期成为新的master。由于挂掉的master可能会有多个slave。Failover的过程需要经过类Raft协议的过程在整个集群内达到一致, 其过程如下:

图2 故障恢复

源码

1,数据结构

clusterState, 从当前节点的视角来看的集群状态,每个节点维护一份
clusterNode,代表集群中的一个节点
clusterLink,负责处理网络上的一条链接来的内容

2,Redis启动过程中与Cluster相关内容

3,客户端请求重定向

4,定时任务 clusterCron

5,集群消息处理 clusterProcessPacket

参考

Table of Contents