Redis集群相关问题

说一说redis的复制功能

在 Redis中,用户可以通过执行SLAVEOF命令或者设置slaveof选项,让一个服务器去复制( replicate)另一个服务器,我们称呼被复制的服务器为主服务器( master ),而对主服务器进行复制的服务器则被称为从服务器( slave ),如图所示。
在这里插入图片描述

旧版本redis复制功能(2.8之前)

Redis 的复制功能分为同步( sync)和命令传播( command propagate)两个操作:

  • 同步操作用于将从服务器的数据库状态更新至主服务器当前所处的数据库状态。
  • 命令传播操作则用于在主服务器的数据库状态被修改,导致主从服务器的数据库状态出现不一致时,让主从服务器的数据库重新回到一致状态。

接下来将对同步和命令传播两个操作进行详细的介绍。

同步

当客户端向从服务器发送SLAVEOF命令,要求从服务器复制主服务器时,从服务器首先需要执行同步操作,也即是,将从服务器的数据库状态更新至主服务器当前所处的数据库状态。从服务器对主服务器的同步操作需要通过向主服务器发送SYNC命令来完成,以下是SYNC命令的执行步骤:

  1. 从服务器向主服务器发送SYNC命令。
  2. 收到SYNC命令的主服务器执行BGSAVE命令,在后台生成一个RDB文件,并使用一个缓冲区记录从现在开始执行的所有写命令。
  3. 当主服务器的BGSAVE命令执行完毕时,主服务器会将BGSAVE命令生成的RDB文件发送给从服务器,从服务器接收并载入这个RDB文件,将自己的数据库状态更新至主服务器执行BGSAVE命令时的数据库状态。
  4. 主服务器将记录在缓冲区里面的所有写命令发送给从服务器,从服务器执行这些写命令,将自己的数据库状态更新至主服务器数据库当前所处的状态。

命令传播

在同步操作执行完毕之后,主从服务器两者的数据库将达到一致状态,但这种一致并不是一成不变的,每当主服务器执行客户端发送的写命令时,主服务器的数据库就有可能会被修改,并导致主从服务器状态不再一致。

举个例子,假设一个主服务器和一个从服务器刚刚完成同步操作,它们的数据库都保存了相同的五个键k1至k5。如果这时,客户端向主服务器发送命令DEL k3,那么主服务器在执行完这个DEL命令之后,主从服务器的数据库将出现不一致:主服务器的数据库已经不再包含键k3,但这个键却仍然包含在从服务器的数据库里面。为了让主从服务器再次回到一致状态,主服务器需要对从服务器执行命令传播操作:主服务器会将自己执行的写命令,也即是造成主从服务器不一致的那条写命令,发送给从服务器执行,当从服务器执行了相同的写命令之后,主从服务器将再次回到一致状态。这就是命令传播

简单的说就是,主服务器对服务器进行的修改命令,从服务器也要执行一次。

旧版复制功能的缺陷
对于初次复制来说,旧版复制功能能够很好地完成任务,但对于断线后重复制来说,旧版复制功能虽然也能让主从服务器重新回到一致状态,但效率却非常低。原因是,断线后要想保持主从一致性,从服务器重新连接后要重新按照初次复制的步骤再来一遍,这就导致之前已存在从服务器中的数据,会被重复操作一遍,既浪费了时间又消耗了cpu的资源。

举个例子,
主从服务器现在保持一致,存储了1000个键值对,这时主从断线,从服务器则尝试重连,在重连的过程中,主服务器存入了<key1, value1>,<key2, value2>两个新的键值对,从服务器重连之后,发现主从不一致,想要保持一致,从服务器就要重新走一遍初次复制的步骤,执行主服务器传过来的rdb文件,而从服务器只想增加两个新的键值对就能保持主从一致,但是rdb文件内确包含了1002个键值对的操作。

新版本redis复制功能(2.8之后)

为了解决旧版复制功能在处理断线重复制情况时的低效问题,Redis 从2.8版本开始,使用PSYNC命令代替SYNC命令来执行复制时的同步操作。PSYNC命令具有完整重同步( full resynchronization)和部分重同步( partial resynchronization)两种模式:

  • 其中完整重同步用于处理初次复制情况:完整重同步的执行步骤和SYNC命令的执行步骤基本一样,它们都是通过让主服务器创建并发送RDB文件,以及向从服务器发送保存在缓冲区里面的写命令来进行同步。
  • 而部分重同步则用于处理断线后重复制情况:当从服务器在断线后重新连接主服务器时,如果条件允许,主服务器可以将主从服务器连接断开期间执行的写命令发送给从服务器,从服务器只要接收并执行这些写命令,就可以将数据库更新至主服务器当前所处的状态。

PSYNC命令的部分重同步模式解决了旧版复制功能在处理断线后重复制时出现的低效情况,下表展示了如何使用PSYNC命令高效地处理上一节展示的断线后复制情况。
在这里插入图片描述部分重同步的实现
部分重同步功能由以下三个部分构成:

  • 主服务器的复制偏移量( replication offset)和从服务器的复制偏移量。
    拿主服务器的复制偏移量和从武器的复制偏移量是否一致,来判断主从服务器是否处于一致状态。
  • 主服务器的复制积压缓冲区( replication backlog )。
    复制积压缓冲区是由主服务器维护的一个固定长度( fixed-size)先进先出(FIFO)队列,默认大小为1MB。用来存储主服务器命令传播的的命令。当进行部分重同步时,先判断复制偏移量后的数据是否存在复制积压缓冲区内,如果存在,则进行部分重同步,否则进行完全同步
  • 服务器的运行ID ( run ID )。
    当从服务器对主服务器进行初次复制时,主服务器会将自己的运行ID传送给从服务器,而从服务器则会将这个运行ID保存起来。当从服务器断线并重新连上一个主服务器时,从服务器将向当前连接的主服务器发送之前保存的运行ID:以次来判断这个服务器是不是之前连接的主服务器

说一说redis的哨兵(Sentinel)模式

Sentinel(哨岗、哨兵)是Redis 的高可用性 ( high availability)解决方案:由一个或多个Sentinel 实例( instance))组成的Sentinel系统( system)可以监视任意多个主服务器,以及这些主服务器属下的所有从服务器,并在被监视的主服务器进入下线状态时,自动将下线主服务器属下的某个从服务器升级为新的主服务器,然后由新的主服务器代替已下线的主服务器继续处理命令请求。

下图展示了一个图16-1展示了一个Sentinel系统监视服务器的例子:
在这里插入图片描述
其中:

  • 用双环图案表示的是当前的主服务器server1。
  • 用单环图案表示的是主服务器的三个从服务器server2、server3 以及server4。
  • server2、server3、server4三个从服务器正在复制主服务器serverl,sentinel系统则在监视所有四个服务器。

假设这时,主服务器server1进入下线状态,那么从服务器server2、server3、server4对主服务器的复制操作将被中止,并且 Sentinel系统会察觉到server1已下线,如下图所示(下线的服务器用虚线表示)。
在这里插入图片描述
当server1的下线时长超过用户设定的下线时长上限时,Sentinel系统就会对server1执行故障转移操作:

  • 首先,Sentinel系统会挑选server1属下的其中一个从服务器,并将这个被选中的从服务器升级为新的主服务器。
  • 之后,Sentinel系统会向server1属下的所有从服务器发送新的复制指令,让它们成为新的主服务器的从服务器,当所有从服务器都开始复制新的主服务器时,故障转移操作执行完毕。
  • 另外,Sentinel还会继续监视已下线的server1,并在它重新上线时,将它设置为新的主服务器的从服务器。

举个例子:
举个例子,下图展示了Sentinel系统将server2升级为新的主服务器,并让服务器server3和server4成为server2的从服务器的过程。
在这里插入图片描述

之后,如果server1重新上线的话,它将被Sentinel系统降级为server2的从服务器,如下图所示。
在这里插入图片描述

redis哨兵模式是如何检测服务器是否下线的?

检测主关下线状态
在默认情况下,Sentinel会以每秒一次的频率向所有与它创建了命令连接的实例(包括主服务器、从服务器、其他Sentinel在内)发送PING命令,并通过实例返回的PING命令回复来判断实例是否在线。

在下图展示的例子中,带箭头的连线显示了Sentinel1和 Sentinel2是如何向实例发送PING命令的:
在这里插入图片描述- Sentinel1将向Sentinel2、主服务器master 、从服务器slave1和 slave2发送 PING命令。

  • Sentinel2 将向Sentinel1、主服务器master 、从服务器slave1和 slave2发送PING命令。实例对PING命令的回复可以分为以下两种情况:有效回复:实例返回+PONG、-LOADING、一MASTERDOWN三种回复的其中一种。
  • Sentinel1将向Sentinel2、主服务器master 、从服务器slave1和 slave2发送 PING命令。Sentinel2 将向Sentinel1、主服务器master 、从服务器slave1和 slave2发送PING命令。

实例对PING命令的回复可以分为以下两种情况:

  • 有效回复:实例返回+PONG、-LOADING、一MASTERDOWN三种回复的其中一种。
  • 无效回复:实例返回除+PONG、-LOADING、一MASTERDOWN三种回复之外的其他回复,或者在指定时限内没有返回任何回复。"

Sentinel配置文件中的down-after-milliseconds选项指定了Sentinel判断实例进入主观下线所需的时间长度:如果一个实例在down-after-milliseconds毫秒内,连续向Sentinel返回无效回复,那么Sentinel会修改这个实例所对应的实例结构,在结构的flags属性中打开SRI_s_DOwN标识,以此来表示这个实例已经进入主观下线状态。

检测客观下线状态

当Sentinel将一个主服务器判断为主观下线之后,为了确认这个主服务器是否真的下线了,它会向同样监视这一主服务器的其他Sentinel进行询问,看它们是否也认为主服务器已经进入了下线状态(可以是主观下线或者客观下线)。当Sentinel 从其他Sentinel那里接收到足够数量的已下线判断之后,Sentinel就会将从服务器判定为客观下线,并对主服务器执行故障转移操作。

说一说哨兵模式的故障转移
在进行故障转移前首先要选举领头Sentinel,由于过程较复杂,请参考《redis设计与实现》16.8节。

在选举产生出领头Sentinel之后,领头Sentinel将对已下线的主服务器执行故障转移操作,该操作包含以下三个步骤:

  • 在已下线主服务器属下的所有从服务器里面,挑选出一个从服务器,并将其转换为主服务器。
  • 让已下线主服务器属下的所有从服务器改为复制新的主服务器。
  • 将已下线主服务器设置为新的主服务器的从服务器,当这个旧的主服务器重新上线时,它就会成为新的主服务器的从服务器。

redis集群方案其他问题

redis 集群模式的工作原理能说一下么?

Redis Cluster是一种服务端Sharding技术,3.0版本开始正式提供。Redis Cluster并没有使用一致性hash,而是采用slot(槽)的概念,一共分成16384个槽。将请求发送到任意节点,接收到请求的节点会将查询请求发送到正确的节点上执行。

  • 通过哈希的方式,将数据分片,每个节点均分存储一定哈希槽(哈希值)区间的数据,默认分配了16384 个槽位
  • 每份数据分片会存储在多个互为主从的多节点上
  • 数据写入先写主节点,再同步到从节点(支持配置为阻塞同步)
  • 同一分片多个节点间的数据不保持一致性
  • 读取数据时,当客户端操作的key没有分配在该节点上时,redis会返回转向指令,指向正确的节点
  • 扩容时时需要需要把旧节点的数据迁移一部分到新节点

在集群模式下,redis 的 key 是如何寻址的?分布式寻址都有哪些算法?

  • hash 算法(大量缓存重建)
  • 一致性 hash 算法(自动缓存迁移)+ 虚拟节点(自动负载均衡)
  • redis cluster 的 hash slot 算法

Redis集群会有写操作丢失吗

Redis并不能保证数据的强一致性,这意味这在实际中集群在特定的条件下可能会丢失写操作。
以下情况可能导致写操作丢失:

  • 过期 key 被清理
  • 最大内存不足,导致 Redis 自动清理部分 key 以节省空间
  • 主库故障后自动重启,从库自动同步
  • 单独的主备方案,网络不稳定触发哨兵的自动切换主从节点,切换期间会有数据丢失

redis集群最大节点个数是多少?

16384个

Redis集群如何选择数据库?

Redis集群目前无法做数据库选择,默认在0数据库。

猜你喜欢

转载自blog.csdn.net/weixin_44533129/article/details/112744745