redis10:多机数据库之一

1、复制

通过执行slaveof让一个服务器去复制另一个服务器。

1.1、旧版复制功能的实现

分为同步和命令传播两个操作:

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

同步步骤

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

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

旧版复制功能的缺点

初次复制;从服务器从来没有复制过任何主服务器,或者当前要复制的主服务器跟上一次复制的主服务器不一样;
断线后重复制:命令传播阶段由于网络原因中断了复制,但是从服务器通过自动重连连上了主服务器,并继续复制主服务器;

  在主从服务器断线期间,主服务器会执行少量写命令,这个数据量一般比整个数据库的数据量要少的多,为了让从服务器补足一小部分缺失的数据却要重新执行一次SYNC命令,做法非常低效;

每次执行SYNC命令,主从服务器需要以下操作:

  • 主服务器需要执行BGSAVE来生成RDB文件,耗费大量的CPU、内存、和磁盘IO资源;
  • 主服务器需要将自己的RDB文件发送给从服务器,会耗费从服务器大量的网络资源(带宽和流量)。
  • 接收到RDB文件的从服务器需要载入RDB文件,在载入期间,从服务器会因为阻塞没办法处理命令请求;

1.2、新版复制功能的实现

为了解决旧版复制功能在处理断线复制时的问题,redis从2.8版本开始,使用PSYNC代替SYNC执行复制时的同步操作。
PSYNC具有完整重同步和部分重同步;

完整重同步用于处理初次复制:和SYNC命令的执行步骤基本一致。
部分重同步用于处理断线后重复制情况:断线后当从服务器重新连接主服务器时,主服务器将断开期间执行的写命令发送给从服务器。

  部分重同步所需的资源比起SYNC少得多,完成同步的速度快得多。执行SYNC需要生成、传送和载入整个RDB文件,而部分重同步只需要将从服务器缺少的写命令发送过去即可;

1.2.1 部分重同步的实现

1、复制偏移量

2、复制积压缓冲区

  • 是由主服务器维护的一个固定长度的先进先出队列,默认大小是1MB.
  • 当服务器进行命令传播时,不仅会将写命令发送给所有从服务器,还会将写命令入队到复制积压缓冲区里面。
  • 当从服务器重新连上主服务器后,从服务器会通过PSYNC命令将自己的复制偏移量offset发送给主服务器:

若是offset之后的数据仍然存在于复制挤压缓冲区里面,主服务器将对从服务器执行部分重同步操作。
如果offset之后的数据不存在,主服务器将对从服务器执行完整重同步操作。

3、服务器的运行ID

  • 每个redis服务器都有自己的运行ID,由40个随机的16进制字符组成;
  • 从服务器对主服务器进行初次复制时,会保存主服务器的运行ID;
  • 从服务器断线并重新连一个主服务器时,从服务器将向当前连接的主服务器发送之前保存的运行ID;

保存的运行ID和当前连接的主服务器运行ID一致,主服务器执行部分重同步操作。
相反地执行完整重同步操作;

1.2.2 心跳检测

在命令传播阶段,从服务器默认会以每秒一次频率向主服务器发送命令:REPLCONF ACK <replication_offset>

  • 检测主从服务器的网络连接状态
  • 辅助实现min-slaves选项
  • 检测命令丢失:主服务器向从服务器补发缺失数据(是在主从服务器没有断线的时候执行)。而部分重同步操作是在断线并重连之后执行;

2、Sentinel

sentinel是redis的高可用性解决方案:一个或者多个sentinel组成的sentinel系统监视任意多个主服务器以及这些主服务器属下的所有从服务器,当被监视的主服务器下线时,自动将下线服务器属下的从服务器升级为新的主服务器。

2.1 启动并初始化sentinel步骤

初始化服务器
sentinel本质上是一个运行在特殊模式下的redis服务器。
使用sentinel专用代码
将一部分普通redis服务器使用的代码替换成sentinel专用代码。
初始化sentinel状态
对sentinel状态的初始化会引发对masters字典的初始化,而masters字典的初始化是根据被载入的sentinel配置文件进行的。
masters字典记录了所有被sentinel监视的主服务器的相关信息:

  • 字典的键是被监视的主服务器的名字;
  • 字典的值是被监视主服务器对应的sentinelRedisInstance结构;
  • 每个sentinelRedisInstance代表一个被sentinel监视的redis服务器实例,这个实例可以是主服务器、从服务器、或者另一个sentinel;

创建连向主服务器的网络连接
sentinel将成为主服务器的客户端,可以向主服务器发送命令,从命令回复中获取相关信息;

  • 对于每个被sentinel监视的主服务器来说,sentinel会创建两个连向主服务器的1异步网络连接:

一个是命令连接,专门用于向主服务器发送命令,并接收命令回复;
另一个是订阅连接,这个连接用于订阅主服务器的__sentinel__:hello频道。

为什么有两个连接

在redis目前的发布与订阅功能中,被发送的信息都不会保存在redis服务器里面,如果在信息发送时,接受信息的客户端不在线或者断线,客户端就会丢失这个消息。为了不丢失__sentinel__:hello的任何信息,sentinel必须专门使用一个订阅连接;
除了订阅频道之外,sentinel还必须向主服务器发送命令,以此来和主服务器进行通信,因此还必须创建命令连接;
sentinel需要与多个实例创建多个网络连接,因此使用异步连接;

2.2 获取主服务器信息

sentinel默认每隔10秒使用命令连接向被监视的主服务器发送INFO命令,通过分析INFO命令的回复来获取主服务器的当前信息;

2.3 获取从服务器信息

当sentinel发现主服务器有新的从服务器出现时,除了会为新的从服务器创建相应的实例结构之外,sentinel还会创建连接到从服务器的命令连接和订阅连接;
在默认情况下,sentinel每隔10秒通过命令连接向从服务器发送INFO命令,并获得回复;

2.4 向主服务器和从服务器发送信息

在默认情况下,sentinel会每隔2秒向所有被监视的主服务器和从服务器发送命令:
在这里插入图片描述
这条命令向服务器的__sentinel__:hello频道发生了一条信息:

  • s_开头的记录的是sentinel本身信息;
  • m_开头的记录的是主服务器的信息。若正在监视的是主服务器,记录的就是主服务器信息;正在监视的是从服务器,记录的是从服务器正在复制的主服务器的信息;

2.5 接收来自主服务器和从服务器的频道信息

当一个sentinel与一个主服务器或者从服务器建立订阅连接之后,会通过订阅连接,向服务器发送:

SUBSCRIBE __sentinel__:hello

在这里插入图片描述

对于监视同一个服务器的多个sentinel来说,一个sentinel发送的消息会被其他sentinel接收到,这些信息会被用于更新其他sentinel对发送方sentinel的认知,也会被用于更新其他sentinel对被监视服务器的认知;

创建连向其他sentinel的命令连接
当sentinel通过频道信息发现一个新的sentinel:

  • 在sentinels字典中为新sentinel创建相应的实例结构
  • 创建一个连向新sentinel的命令连接;
  • 新sentinel同样创建命令连接;
  • 最终监视同一个主服务器的多个sentinel形成相互连接的网络。

2.6 检查主观下线状态

每秒一次向所有与他建立了命令连接的实例发送PING命令,通过回复判断是否下线;
若是一段时间内都返回无效回复,则判断主观下线;

2.7 检查客观下线状态

当sentinel将一个主服务器判断为主观下线之后,为了确认是否真的下线,会向同样监视这一个主服务器的其他sentinel询问。

2.8 选举领头sentinel

当一个主服务器被判断为客观下线后,监视这个主服务器的各个sentinel会进行协商选举出一个领头sentinel,对下线主服务器执行故障转移操作;

2.9 故障转移

假设已下线主服务器叫做A;

  • 从A属下的所有从服务器里面挑选出一个从服务器并将其转换为主服务器;
  • A属下的所有从服务器改为复制新的主服务器;
  • 将A设置为新的主服务器的从服务器;

猜你喜欢

转载自blog.csdn.net/qq_37935909/article/details/108910050