Redis Cluster原理分析

一、数据分布:

所谓数据分布就是将数据分散到各个Redis节点中去。
Redis进行数据分布采用的是 一致性哈希+虚拟槽 的方式。
关于一致性哈希,看程序员小灰:一致性哈希介绍

因为一致性哈希存在存储数据结点分布不均匀,从而导致数据也分布不均与的现象,并且这种现象在结点少的时候更容易出现。另外当数据结点较少时,改变其中的结点,带来的数据迁移量会越大。
所以Redis使用了虚拟槽(slot),虚拟槽就是把数据通过哈希函数映射到一个固定的整数范围内,这个范围一般远远大于预计的结点数量。每个槽就是整数范围里的一个整数,即一个slot。Redis中槽的数量为16383个。使用槽后,数据的管理与迁移是以槽为单位。
在Redis中每个存储数据的节点映射一部分数量的槽(16383/结点个数)。现在假设放入一个key-value,首先通过hash(key)%16383映射到某个slot,该slot映射在某个存储结点,然后把key-value放入该结点。

二、建立集群:

假设有6个结点。分别为1,2,3,4,5,6.

1. 结点间建立集群关系:
通过发送 cluster meet ip 端口号命令,将指定IP和端口号的结点加入集群。
结点1,依次向2,3,4,5,6发送cluster meet。然后通过cluster nodes查看,就可以发现当前集群已经有6个结点。

过程:
结点1向2发送meet命令,保存2的信息;
结点2接收到1的meet命令,保存1的信息,并向1反馈PONG命令;
之后1,2结点通过PING,PONG进行正常的结点通信。

2. 分配slot:
在未给结点分配slot时,结点不能响应读写操作。
使用cluster addslots为结点分配slot,slot的分配应该均匀。
注意:任意一个slot未分配,集群就不可用。

使用cluster info可以查看slot的分配。

3. 建立主从关系:
Redis Cluster保证高可用,所以需要搭建主从。
在从节点4,5,6上使用cluster replicate nodeId建立主从关系。
这里的nodeId 是主节点以集群模式启动时生成的48位的16进制id,与runId不同,他只会创建一次。

工具:
当集群中结点较多时,使用上述流程较麻烦。一般使用 redis-trib.rb来进行搭建。

三、集群间的通信:

Redis集群使用P2P形式的Gossip协议进行集群中结点间的数据交换。Gossip协议原理就是结点间不断通过PING,PONG进行通信交换信息,一段时间后,就会得到所有的结点信息。

Gossip协议:
Gossip协议的目的就是进行节点间的数据交换。数据交换就是通过发送Gossip消息。
Gossip消息分为:ping , pong , meet, fail四种。

meet消息:
通知其他节点加入集群。

ping消息: 集群中结点交互最频繁的消息,每秒向其他节点发送一个ping命令,以便知道其他节点的存活状态,并进行数据状态信息交互。ping命令包含了发送者自身及其它部分节点的数据状态信息。

pong:
作为ping与meet的响应消息,包含响应者自身的信息。

fail:
当发现某个结点下线时,会向其他节点广播发送fail信息,其他节点接收后,会将自己记录的对应结点状态更新为下线。

四、集群伸缩:

集群进行伸缩时,进行数据迁移是以slot为单位的。也就是把原先各个节点的slot分配部分给新的结点进行分担。
从这里也可以看出,Redis Cluster的伸缩带来的影响很小。首先只用迁移部分数据,并且当客户端获取某个数据时,是根据数据的key映射到slot,slot再与结点映射。

1. 集群扩容:
假设加入7,8两个结点,在任意一个集群结点上使用meet命令,将7,8加入集群。加入集群后,7,8结点由于没有分配slot,所以暂时无法使用。

对于加入的新的结点,可以作为已有的主节点的从节点进行故障转移,或者是作为主节点分担存储与写的压力。

这里将7作为新的主节点,8作为7的从节点。原来16383个slot由1,2,3三个结点均分为3等分,现在7加入,那么1,2,3分出自己的slot给7,让4个主结点的slot近似相等。分出slot的时候,将slot映射的数据也转移到7.

2. 集群收缩:
下线的如果是主节点,也就是该结点映射的有slot,就把该slot均分给剩余的主节点。当处理完slot或者下线的是从节点,则广播fail消息,让其他结点更新该下线结点的状态。

五、故障转移:

Redis Cluster自身保证高可用,也就是允许出现部分节点故障。当发生故障时,集群能够发现并转移故障。

1. 故障发现:
这里一个结点的下线也分为主观下线与客观下线 :

  • 主观下线:
    当结点A向结点B发送ping命令后,在指定时间内未收到回复,就会将自己维护的状态信息中,把B结点标记为主观下线。

  • 客观下线:
    因为Gossip消息传播,结点A标记结点B为主观下线的信息会传播给其他结点。当其他节点发现接收的ping命令时,发现包含把B结点设置为主观下线时,就会判断是否有半数以上的主节点同意B结点下线,当符合时,当前结点就会把结点B标记为客观下线,然后广播发送fail命令,通知其他的结点。

    这里之所以进行投票的是主节点,是因为主节点才是维护slot的结点,负责读写与管理slot等关键信息,而从节点只复制主节点的数据与状态信息。

2. 故障恢复:
当客观下线的结点是维护slot的主节点,为了保证高可用,要进行故障转移。故障转移工作由该结点的所有从节点负责。

故障转移步骤:

  • 进行资格省察:
    从节点看自己最后一次与主节点断开连接的时间是否超过限制,若未超过,则具有晋身为主节点的资格。
  • 设置选举时间:
    从节点根据自己的复制偏移量的大小,设置自己的选举开始时间。偏移量越大代表复制的数据越完整,那么他的选举开始时间越小。可以看出,设置选举时间的作用是为定义一个优先级。
  • 进行选举:
    从节点向集群其它结点发送选举信息,主节点参与投票,当收到主节点个数一半以上的投票时,当前从节点选举为新的主节点。比如有5个主节点,5/2+1=3,也就是说挂掉一个后,需要在剩下4个主节点中获得3票才能选举成功。
  • 替换下线的主节点:
    撤销下线主结点的slot,并交由自己管理,然后广播通知其他节点,自己已经接管了这部分slot。

猜你喜欢

转载自blog.csdn.net/qq_40728028/article/details/106600685