我们知道,为了帮助数据库缓解高并发的压力,我们会上reids缓存帮助数据库分摊,虽说常见场景的并发量还不足以让redis宕机,但假设出现了极高的并发场景,redis依旧是有宕机的可能的,毕竟单点部署的redis容易出现的问题很多,而为了优化这一点,reids就衍生出了许多集群来帮助reids来实现高可用。
1.什么是redis的集群,redis的集群都有哪些
redis集群是 redis 官方提供的分布式解决方案,用于将数据自动分片到多个节点上,实现数据的拓展,同时提供高可用性,通过redis的集群可以帮助redis解决一些单点布置会发生的一系列故障问题。
redis的集群主要是分主从集群,哨兵集群以及分片集群,当然还存在其他的为特殊需求所构建的集群,不过我们重点需要学习的就是这三种集群。
2.redis的主从集群
当部署的单点redis宕机以后,大量的请求就会打入数据库,为了解决这种情况我们就会部署多个redis来组成主从集群,从中的节点分为主节点和从节点两个身份,主节点只允许写入数据而从节点只允许读取数据,而从节点的数据通过主从复制来从主节点中获取数据。
主从复制具体的是分成两种形式,分别是全量复制和增量复制,接下来我会区分二者讲解:
全量复制:
执行时机:当部署新的从节点或者旧的从节点在宕机很久后恢复
基本概念:意味着从节点会复制主节点的全量数据
底层实现:主节点执行bgsave的命令生成RDB文件,发送给从节点,而从节点获取到RDB文件后会加载到内存当中,这就获取了全量数据,假设RDB文件制作过程中又有新的写命令进入,那就通过将命令存入暂存区,在同步完后发送。
增量复制:
执行时机:当从节点已经包含一定数据,且一直正常运行或宕机时间不长
基本概念:意味着从节点会不断的获取主节点新增的数据
底层实现:当主从完成全量复制以后会通过TCP维持一个主从的长连接,这样在获取到新的写操作命令后,主节点就会异步的将这些写命令发送给从节点。
这里有个小知识点,为什么全量复制要使用RDB而非AOF?这个原因有两点,第一是RDB保存的二进制的数据文件,而AOF保存的是写命令,相比之下RDB的文件更小更轻巧。第二就是RDB的数据恢复速度很快,而AOF的是执行写命令操作,这样效率就很慢了。
这样的一个集群具有两个好处,首先部署多台redis可以分散请求,降低单点的并发量,其次即使主节点依旧被海量压力冲跨,或者出现意外导致宕机,可以通过主从集群的特性来选举新的主节点,并同时监控宕机的主节点在恢复后设置为从节点。
3.redis的哨兵集群
我们可以想象一个场景,按照redis自己所处的主从情况之下,我们会发现假设主节点宕机,就需要手动的从多个从节点中推举出一个新的主节点,再手动的转从为主,这光是看着就很麻烦,因此redis就创造了哨兵集群,哨兵集群能够自动监控所有redis节点的状态,假设主节点宕机,就会自动的做主从故障的转移,这样就会方便许多。
那哨兵集群究竟是怎么知道主节点宕机的呢?
哨兵集会和其他节点建立一个心跳检测,不断的向主节点发送ping的命令,而一旦发现主节点长时间没有回应,这个哨兵节点就会判断主节点为主观下线,但是一个哨兵节点长时间接受不到主节点回应的因素是很多的,例如网络因素等,因此只能判断为主观下线,所以一般来说只有一个集群中超半数的哨兵节点都认为主节点下线,这个主节点才会被判断为客观下线。
在哨兵节点判断主节点宕机以后,如何选择新的主节点呢?
首先哨兵集群会通过raft的leader算法来选举哨兵当中的leader节点,后用这个leader节点来选举新的主节点,具体的规则如下:
在选取新的主节点后,会通过主从复制将新选举的主节点的数据复制给其他从节点,之后就会将新的主节点数据发送给客户端。
而在设置好新的主节点后,哨兵leader依旧会继续监视旧的主节点,当旧的主节点恢复后就会将其设置为新的从节点。
4.redis的分片集群
对比最原始的主从集群,我们会发现几个问题:
首先不论主节点还是从节点存储的都是全量数据,虽说在创建主从的时候是部署了多台redis,但在最终的存储量依旧是要看主节点的内存量的,因此原始的主从内存量是单机情况内存是不够的,就算勉强够用,也会导致RDB文件变大使得每次数据复制的速度变慢。
其次就是只有单一的主节点能执行写操作,假设需要设置另一个类型的数据库,就无法拓展新的写操作命令。
正因为有这两个问题存在,redis的分片集群也就诞生了,redis的分片集群是部署多台redis组成集群,每个redis节点都可以单独做写操作,并且可以分散存储数据,不过这里有一个问题,就是redis节点可能会出现宕机的情况,为了解决这个问题,我们会对每个节点做主从,因此分片集群可以粗略当成多个主从集群组成的集群。
为了做数据分片,分片集群准备了16384个hash槽,将这些槽平均分给不同的节点,当数据进入时,使用CRC16算法去获取到数据应当存储槽的位置,不过在槽发生扩容缩容的时候可能会导致槽的位置迁移,不过分片集群会做一个检测,假设槽与对应的节点不匹配,就会通知客户端并重新匹配。
为了完成节点之间的通信,redis集群利用了Gossip协议,具体方式如下:
而分片集群的主从故障也是通过Gossip协议来检测其他的节点而非像基础的哨兵集群,各个主节点会互相检测,假设一半以上主节点认为某个主节点宕机,就会通过其从节点找出新的主节点,再用fail通知其他的节点。
今天的分享就到这里了,希望这篇博客能给你一些帮助,让你对关于redis的集群的问题得到进一步的提升,在面试的时候能从容面对面试官。