个人博客

爱写代码的小书童

马上订阅 个人博客 RSS 更新: https://zofun.github.io/atom.xml

高可用Redis:Redis Cluster

2020年5月1日 22:20

Redis Cluster是Redis官方提供的Redis集群功能。

为什么现需要Redis Cluster

  1. 主从复制不能满足高可用的要求
  2. 随着业务的发展,需要更高的QPS
  3. 数据量的增长导致服务器内存不足以存储
  4. 网络流量的增长,业务的流量已经超过了服务器的网卡的上限值,可以考虑使用分布式技术来进行分流。
  5. 离线计算,需要中间环节缓冲等别的需求。

数据分布

当单机的redis节点无法满足要求,按照分区规则把数据分到若干个子集中。

常见的数据分布方法

顺序分布

比如有1-100个数据,要保存的三个节点上,那么1-33号数据放在第一个节点上,34-66号数据放在第二个节点上,依此类推。

哈希分布

对键进行hash后,根据哈希码,来进行分区。

常见的分区方式有:

  1. 节点取余分区:对key进行hash之后,与节点数进行取余运算,根据余数不同保存在不同的节点上。该分区方式的问题就是不利于节点数量的调整。但节点数量变动时,大量的数据需要迁移。
  2. 一致性哈希分区:将所有的数据当作一个token环,token环中的数据范围时0到2的32次方,然后为每一个数据节点分配一个token范围值,这个节点就负责保存这个节点范围的数据。对每一个key进行hash运算,将哈希后的结果在哪个token范围内,则按照顺时针去找最近的节点,这个key就会被保存在这个节点上。
  3. 虚拟槽分区:虚拟槽分区时Redis Cluster采用的分区方式,预设虚拟槽,每个槽就相当于一个数字,有一定的范围。每个槽映射一个数据子集,一般比节点数大。Redis cluster中预设的虚拟槽的范围为0到16383

虚拟槽分区的步骤:

1
2
3
4
5
6
7
1.把16384槽按照节点数量进行平均分配,由节点进行管理
2.对每个key按照CRC16规则进行hash运算
3.把hash结果对16383进行取余
4.把余数发送给Redis节点
5.节点接收到数据,验证是否在自己管理的槽编号的范围
如果在自己管理的槽编号范围内,则把数据保存到数据槽中,然后返回执行结果
如果在自己管理的槽编号范围外,则会把数据发送给正确的节点,由正确的节点来把数据保存在对应的槽中

虚拟槽分区的特点:
使用服务器端话管理节点,槽,数据
可以对数据进行打散,又可以保证数据分布均匀。

Redis Cluster基本架构

节点

Redis Cluster是分布式架构,即Redis Cluster中有多个节点,每个节点购汇负责数据读写操作,每个节点之间会进行通信,

meet操作

节点之间会互相通信
meet操作时节点之间完成相互通信的基础,meet操作有一定的频率和规则。

分配槽

把16384个槽平均分配给节点进行管理,每个节点只能对自己负责的槽进行读写。由于每个节点之间都彼此通信,每个节点都知道另外节点负责管理的槽范围。
客户端访问任意任意节点时,对数据key按照CRC16规则进行hash运算,然后对运算结果对16383进行取余,如果余数在当前访问的节点管理的槽的范围内,则直接返回对应的数据,否则会告诉客户端去哪个节点获取数据,由客户端去正确的节点获取数据。

复制

保证高可用,每个主节点都有一个从节点,当主节点故障,cluster会按照规则实现主备的高可用

客户端路由

moved重定向

1
2
3
4
5
6
1. 每个节点通过通信都会共享redis cluster中槽和集群中对应节点的关系
2. 客户端向redis cluster的任意节点发送命令,接收命令的节点会根据CRC16规则进行hash算法与16383取余,计算自己的槽和对应节点
3. 如果保存数据槽被分配给当前节点,则去槽中执行命令,并把命令执行结果返回给客户端
4. 如果保存数据的槽不再当前节点的管理范围内,则向客户端返回moved重定向异常
5. 客户端接收到节点返回的节点,如果时moved异常,则从moved异常中获取目标节点的信息
6. 客户端向目标节点发送命令,获取命令执行命令。

ask重定向

对集群进行扩容和缩容时,需要对槽及槽中的数据进行迁移。
当客户端向某个节点发送命令,节点向客户端返回moved异常,告诉客户端数据对应的槽节点信息。如果此时正在进行集群拓展或者缩空操作,当客户端向正确的节点发送命令时,槽及槽中数据已经被迁移到被的节点了,就会返回ask。
步骤:

1
2
3
1. 客户端向目标节点发送命令,目标节点中的槽已经迁移到别的节点上,此时目标节点会返回ask转向给客户端
2. 客户端向新的节点发送asking命令给新的节点,然后再次给新节点发送命令
3. 新节点执行命令,把命令执行结果返回给客户端。

故障发现

Redis cluster通过pin/pong消息实现故障发现,不需要sentinel。
ping/pong不仅能传递节点与槽的对应消息,也能传递其它状态,比如:节点主从状态,节点故障等。

主观下线

主观下线只代表一个节点对另一个节点的判断,不代表所有节点的认知。

1
2
3
4
1. 节点1定期发送ping消息给节点2
2. 如果发送成功,代表节点2正常运行,节点2会响应pong消息给节点1,节点1更新与节点2的最后通信时间
3. 如果发送失败,则节点1和节点2之间的通信异常判断连接,在下一个定时任务周期时,仍然会与节点2发送ping消息。
4. 如果节点1发送与节点2最后通信时间超过node-timeout,则把节点2标识为pfail状态

JXzyVJ.png

客观下线

当半数以上持有槽的主节点都标记某节点主观下线时,可以保证判断的公平性。
客观下线流程:

1
2
1. 某个节点接收到其它节点发送的ping信息,如果接收到的ping消息中包含了其它pfail节点,这个节点会将主观下线消息添加到自身的故障列表中,故障列表中包含了当前节点接收到的每一个节点对其它节点的状态信息。
2. 当前节点把主观下线的消息内容添加到故障列表之后,会尝试对故障节点进行客观下线操作。

故障恢复

资格检查

1
2
3
4
5
对从节点的资格进行检查,只有难过检查的从节点才可以开始进行故障恢复
每个从节点检查与故障主节点的断线时间
超过cluster-node-timeout * cluster-slave-validity-factor数字,则取消资格
cluster-node-timeout默认为15秒,cluster-slave-validity-factor默认值为10
如果这两个参数都使用默认值,则每个节点都检查与故障主节点的断线时间,如果超过150秒,则这个节点就没有成为替换主节点的可能性

准备选举时间

使偏移量最大的从节点具备优先级成为主节点的条件。
Jjpo4A.png

选举投票

对选举出来的多个从节点进行投票,选出新的主节点
Jjpqjf.png

替换主节点

当前从节点取消复制变成离节点。执行cluster del slot撤销故障主节点负责的槽,并执行cluster add slot把这些槽分配给自己
向集群广播自己的pong消息,表明已经替换了故障从节点