目录
1. redis集群方案有哪些
在Redis中提供的集群方案总共有三种(一般一个redis节点不超过10G内存)
- 主从复制 / 主从模式 解决高并发问题
- 哨兵模式 解决高可用问题
- 分片集群
2. 主从复制(主从数据同步)
2.1 主从复制定义
主从复制,是指将一台Redis服务器的数据,复制到其他的Redis服务器。
前者称为主节点(Master),后者称为从节点(Slave);数据的复制是单向的,只能由主节点到从节点。
默认情况下,每台Redis服务器都是主节点;且一个主节点可以有多个从节点(或没有从节点),但一个从节点只能有一个主节点
Redis主从复制服务器架构图如下:
2.2 如何搭建主从架构
主从模式是其中最简单的模式,这种模式中,Redis被分为主节点(master)和从节点(slave/replica) 。主节点可以进行读、写操作,而从节点一般只能进行读操作,如果在从节点上进行写操作,Redis会报错。主节点和从节点会进行数据同步,使节点上的数据保持一致。
假设我们现在有3台计算机A、B、C作为Redis节点,我们要用它们来搭建主从架构,把A作为master(主节点)。
① 基本配置:首先,我们要在这3个节点上都安装。为保证这3个节点的Redis状态是一样的,因此把A的Redis配置文件复制并覆盖另外两个节点的Redis配置文件。然后启动3个节点上的Redis。
② 开启主从关系:要配置主从可以使用replicaof或者slaveof命令,这两条命令是一样的,只是Redis在5.0版本之后把从节点的名字从slave改成了replica。
有两种方式可以进行配置:临时和永久。
永久配置:在从节点的Redis配置文件(通常是redis.conf)中添加一行配置:slaveof <masterip> <masterport>。其中,后两个参数分别是主节点的ip地址和Redis端口号。
临时配置:使用redis-cli客户端连接到redis服务,执行slaveof命令(重启后失效):slaveof <masterip> <masterport>。
2.3 主从复制同步原理
2.3.1 全量同步
在6步骤中,master节点会进行一次bgsave操作生成RDB文件,再把这个RDB文件发给slave节点。我们知道,在bgsave期间,Redis仍然能进行服务,如果在这段时间内,master执行了写操作,那么主从节点之间的数据就会产生差异。因此,master节点会把bgsave执行期间的所有命令都记录到repl_backlog(上图把名字写错了)文件中,然后在发送RDB文件之后,把repl_backlog中的命令发送给从节点(图中的10操作)。从节点会执行这些命令,从而保证主从间的数据是一致的。
tip:如果不懂bgsave命令则请看 详谈redis数据持久化(RDB、AOF)_rdb和aof-优快云博客
Q:一个问题,master是如何得知slave节点是第一次与它建立连接的呢?
A:关于这个问题,首先我们要了解两个概念Replication Id和offset:replid和offset
Replication Id:简称replid,是数据集的标记,id一致则说明是同一数据集。每一个master都有唯一的replid,slave则会继承master节点的replid
offset:偏移量,随着记录在repl_baklog中的数据增多而逐渐增大。slave完成同步时也会记录当前同步的offset。如果slave的offset小于master的offset,说明slave数据落后于master,需要更新。
slave要进行数据同步时,需要告诉master自己的Replication Id和offset。
由于slave原本也是一个master,因此它也有自己的Replication Id和offset,并且和master的不一样。
master判断发现slave发送来的Replication Id与自己的不一致,说明这是一个全新的slave,就知道要做全量同步了。此外,master会将自己的Replication Id和offset都发送给这个slave,因此从,经过第一次全量同步之后,slave的Replication Id就和master的一样了。
2.3.2 增量同步
通过bgsave生成RDB是一个比较消耗性能的操作。因此除了第一次做全量同步,其它大多数时候slave与master都是做增量同步。
增量同步就是只更新slave与master存在差异的部分数据(与offset有关了)。
2.4 主从复制优缺点
优点:解决了系统的高并发读的问题。
缺点:无法保证系统的高可用,所以哨兵模式出现了。
3. 哨兵模式
3.1 哨兵模式的作用
1、监控
2、自动故障恢复
3、通知redis客户端
Sentinel在本质上是一个独立的进程。Sentinel的作用如下:
- 监控:Sentinel 会不断检查您的master和slave是否按预期工作。
- 自动故障恢复:如果master故障,Sentinel会将一个slave提升为master。当故障实例恢复后也以新的master为主。
- 通知:Sentinel充当Redis客户端的服务发现来源,当集群发生故障转移时,会将最新信息推送给 Redis的客户端。
3.2 哨兵的监控(心跳机制、选主规则)
3.2.1 Sentinel是如何进行监控的(心跳机制)
Sentinel基于心跳机制监测服务状态,每隔1秒向集群的每个实例发送ping命令:
- 主观下线:如果某sentinel节点发现某实例未在规定时间响应,则认为该实例主观下线。
- 客观下线:若超过指定数量(quorum)的sentinel都认为该实例主观下线,则该实例客观下线。quorum值最好超过Sentinel实例数量的一半。
3.2.2 选主规则
一旦发现主节点客观下线了。哨兵会推举新的主节点,选主规则如下:
判断主与从节点断开时间长短,如超过指定值就排除该从节点
然后判断从节点的slave-priority值,越小优先级越高
如果slave-prority一样,则判断slave节点的offset值,越大(说明从节点数据与主节点越相近) 优先级越高
最后是判断slave节点的运行id大小,越小优先级越高。
总结下来就是,先排除断开过久的,然后看提前设置的优先值,最后看数据丢失的情况。
3.3 集群(哨兵模式)脑裂
如果此时原本的主节点(暂时称为A)因为网络问题,使得主从节点处在不同的网络分区,哨兵监测不到主节点(没有回应心跳),那么哨兵便会进行选举出一个新的主节点(暂时称为B),这样就存在了两个主节点,像是大脑分两列了一样。等A节点网络恢复之后才会由主节点降为从节点。这个过程称为脑裂。
当然如果是哨兵监测不到从节点,则会去除这个从节点
3.3.1 脑裂产生的流程
上图是一个正常情况下的哨兵模式,但是由于网络问题,没有回应心跳,那么哨兵便会进行选举出一个新的主节点(暂时称为B),这样就存在了两个主节点,像是大脑分两列了一样。如下图:
就这样上图就存在了两个主节点,像是大脑分两列了一样,且此时客户端还是连接的第一个master主节点,并继续写数据,等到网络恢复后第一个master会自动把自己变为从节点(我们暂时叫从节点A)如下图:
从节点A向主节点同步数据时,由于发现数据不一致,就会删除自己原来的数据,进行同步,造成数据丢失的问题
3.3.2 集群(哨兵模式)脑裂解决方案
解决方案有两种,对应着redis的两个配置参数:
min-slaves-to-write
:设置主节点在至少有指定数量的从节点确认写操作的情况下才执行写操作min-salves-max-lag
:设置从节点的最大延迟(以秒为单位),如果从节点的延迟超过这个值,则该从节点不会被计入min-slaves-to-write
的计数中举个例子:当
min-slaves-to-write
设置为 2,min-slaves-max-lag
设置为 10 秒时,主节点只有在至少有 2 个从节点延迟不超过 10 秒的情况下才会接受写操作。这两个参数就使得发生脑裂的时候,如果某个主节点跟随的从节点数量不够或延迟较大,就无法被写入,这样就能避免脑裂导致的数据不一致。
建议集群部署奇数个节点,例如集群数为 5,那么可以设置
min-slaves-to-write
为 3,min-slaves-max-lag
为 5-10 秒。
4.分片集群
4.1 分片集群结构
它的结构特点为:
- 集群中有多个master,每个master保存不同数据,且每个master都可以有多个slave节点。这样就解决了海量数据存储,高并发读写的问题。相当于把主从模式概括进来了。
- 不再需要哨兵,直接master之间通过ping监测彼此健康状态。只要超过一定数量的master节点认为某个master节点宕机了,那么那个节点就客观下线了。相当于变形的哨兵模式。
- 客户端请求可以访问集群任意节点,经过一定的路由规则,最终都会被转发到正确节点。
4.2 路由规则
Redis 分片集群引入了哈希槽的概念,Redis 集群有 16384 个哈希槽,每个 key通过 CRC16 校验后对 16384 取模来决定放置哪个槽,集群的每个节点负责一部分 hash 槽。这样能保证客户端请求不冲突地正确转发到redis的某个master节点上。
4.3 分片集群优缺点
优点:解决了系统的海量数据存储、高可用、高并发读写的问题。
缺点:集群维护很麻烦,而且集群之间的通信和心跳检测消耗大量的网络带宽,无法使用lua脚本和事务。
5. 相关面试题
5.1 Redis集群有哪些方案?
在Redis中提供的集群方案总共有三种:
主从复制、
哨兵模式、
Redis分片集群
5.2 介绍一下主从同步
单节点Redis的并发能力是有上限的,要进一步提高Redis的并发能力,可以搭建主从集群,实现读写分离。一般都是一主多从,主节点负责写数据,从节点负责读数据,主节点写入数据之后,需要把数据同步到从节点中。
5.3 说一下主从同步数据的流程
主从同步分为了两个阶段,一个是全量同步,一个是增量同步。
全量同步是指从节点第一次与主节点建立连接的时候使用全量同步,流程是这样的:
第一:从节点请求主节点同步数据,其中从节点会携带自己的replication id和offset偏移量。
第二:主节点判断是否是第一次请求,主要判断的依据就是,主节点与从节点是否是同一个replication id,如果不是,就说明是第一次同步,那主节点就会把自己的replication id和offset发送给从节点,让从节点与主节点的信息保持一致。
第三:在同时主节点会执行bgsave,生成rdb文件后,发送给从节点去执行,从节点先把自己的数据清空,然后执行主节点发送过来的rdb文件,这样就保持了一致。
当然,如果在rdb生成执行期间,依然有请求到了主节点,而主节点会以命令的方式记录到缓冲区,缓冲区是一个日志文件(repl_backlog),最后把这个日志文件发送给从节点,这样就能保证主节点与从节点完全一致了,后期再同步数据的时候,都是依赖于这个日志文件,这个就是全量同步
增量同步指的是,当从节点服务重启之后,数据就不一致了,所以这个时候,从节点会请求主节点同步数据,主节点还是判断不是第一次请求,不是第一次就获取从节点的offset值,然后主节点从命令日志中获取offset值之后的数据,发送给从节点进行数据同步。
tip:如果不懂bgsave命令则请看详谈redis数据持久化(RDB、AOF)_rdb和aof-优快云博客
5.4 怎么保证Redis的高并发、高可用
答:使用哨兵模式搭建redis集群
详细回答:
首先可以搭建主从集群,再加上使用redis中的哨兵模式,哨兵模式可以实现主从集群的自动故障恢复,里面就包含了对主从服务的监控、自动故障恢复、通知;如果master故障,Sentinel会将一个slave提升为master。当故障实例恢复后也以新的master为主;同时Sentinel也充当Redis客户端的服务发现来源,当集群发生故障转移时,会将最新信息推送给Redis的客户端,所以一般项目都会采用哨兵的模式来保证redis的高并发高可用。
5.5 你使用redis是单点还是集群,哪种集群
答:主从(1主1从)+哨兵就可以了。单节点不超过10G内存,如果Redis内存不足则可以给不同服务分配独立的Redis主从节点
详细回答:
候选人:我当时使用的是主从(1主1从)加哨兵。一般单节点不超过10G内存,如果Redis内存不足则可以给不同服务分配独立的Redis主从节点。尽量不做分片集群。因为集群维护起来比较麻烦,并且集群之间的心跳检测和数据通信会消耗大量的网络带宽,也没有办法使用lua脚本和事务
5.6 redis集群脑裂,该怎么解决呢?
集群脑裂是由于主节点和从节点和sentinel处于不同的网络分区,使得sentinel没有能够心跳感知到主节点,所以通过选举的方式提升了一个从节点为主,这样就存在了两个master,就像大脑分裂了一样,这样会导致客户端还在老的主节点那里写入数据,新节点无法同步数据,当网络恢复后,Sentinel会将老的主节点降为从节点,这时再从新master同步数据,就会导致数据丢失
redis集群脑裂问题,在项目中很少见,不过是这样解决的
解决:我们可以修改redis的配置,可以设置最少的从节点数量以及缩短主从数据同步的延迟时间不能超过5秒,达不到要求就拒绝请求,就可以避免大量的数据丢失(如果这里看不懂请重新看 3.3.2)
5.7 redis的分片集群有什么作用
分片集群主要解决的是,海量数据存储的问题,集群中有多个master,每个master保存不同数据,并且还可以给每个master设置多个slave节点,就可以继续增大集群的高并发能力。同时每个master之间通过ping监测彼此健康状态,就类似于哨兵模式了。当客户端请求可以访问集群任意节点,最终都会被转发到正确节点
5.8 Redis分片集群中数据是怎么存储和读取的?
在redis集群中是这样的
Redis 集群引入了哈希槽的概念,有 16384 个哈希槽,集群中每个主节点绑定了一定范围的哈希槽范围, key通过 CRC16 校验后对 16384 取模来决定放置哪个槽,通过槽找到对应的节点进行存储。