Redis(设计与实现):37---复制之旧版复制功能(Redis 2.8版本之前、SYNC命令)

  • Redis的复制功能分为下面两个操作:
    • 同步操作(sync)用于将从服务器的数据库状态更新至主服务器当前所处的数据库状态
    • 命令传播操作(command propagate)则用于在主服务器的数据库状态被修改,导致主从服务器的数据库状态出现不一致时,让主从服务器的数据库重新回到一致状态
  • 旧版复制是指在Redis 2.8版本之前的功能

一、同步(SYNC命令)

  • 概念:当客户端向从服务器发送SLAVEOF命令,要求从服务器复制主服务器时,从服务器首先需要执行同步操作,也即是,将从服务器的数据库状态更新至主服务器当前所处的数据库状态
  • SYNC命令:从服务器对主服务器的同步操作需要通过向主服务器发送SYNC命令来完成,以下是SYNC命令的执行步骤:
    • ①从服务器向主服务器发送SYNC命令
    • ②收到SYNC命令的主服务器执行BGSAVE命令,在后台生成一个RDB文件,并使用一 个缓冲区记录从现在开始执行的所有写命令
    • ③当主服务器的BGSAVE命令执行完毕时,主服务器会将BGSAVE命令生成的RDB文件发送给从服务器,从服务器接收并载入这个RDB文件,将自己的数据库状态更新至主服务器 执行BGSAVE命令时的数据库状态
    • ④主服务器将记录在缓冲区里面的所有写命令发送给从服务器,从服务器执行这些写 命令,将自己的数据库状态更新至主服务器数据库当前所处的状态
  • 下图展示了SYNC命令执行期间,主从服务器的通信过程:

Redis(设计与实现):37---复制之旧版复制功能(Redis 2.8版本之前、SYNC命令)_第1张图片

演示案例

  • 下表展示了一个主从服务器进行同步的例子

Redis(设计与实现):37---复制之旧版复制功能(Redis 2.8版本之前、SYNC命令)_第2张图片

二、命令传播

  • 在同步操作执行完毕之后,主从服务器两者的数据库将达到一致状态,但这种一致并不是一成不变的,每当主服务器执行客户端发送的写命令时,主服务器的数据库就有可能会被修改,并导致主从服务器状态不再一致
  • 为了让主从服务器再次回到一致状态,主服务器需要对从服务器执行命令传播操作:主 服务器会将自己执行的写命令,也即是造成主从服务器不一致的那条写命令,发送给从服务器执行,当从服务器执行了相同的写命令之后,主从服务器将再次回到一致状态
  • 例如,主服务器执行了DEL k3的命令,那么主服务器将向从服务器发送相同的命令DEL k3,当从服务器执行完这个命令之后,主从服务器将再次回到一致状态,现在主从服务器两者的数据库都不再包含键k3了。如下图所示:

Redis(设计与实现):37---复制之旧版复制功能(Redis 2.8版本之前、SYNC命令)_第3张图片

三、旧版复制功能的缺陷(断线之后重新复制)

  • 在Redis中,从服务器对主服务器的复制可以分为以下两种情况:
    • 初次复制:从服务器以前没有复制过任何主服务器,或者从服务器当前要复制的主服务 器和上一次复制的主服务器不同。
    • 断线后重复制:处于命令传播阶段的主从服务器因为网络原因而中断了复制,但从服务 器通过自动重连接重新连上了主服务器,并继续复制主服务器
  • 对于初次复制来说,旧版复制功能能够很好地完成任务,但对于断线后重复制来说,旧版复制功能虽然也能让主从服务器重新回到一致状态,但效率却非常低

演示案例(服务器断线之后重新复制)

Redis(设计与实现):37---复制之旧版复制功能(Redis 2.8版本之前、SYNC命令)_第4张图片

  • 在时间T10091,从服务器终于重新连接上主服务器,因为这时主从服务器的状态已经不再一致,所以从服务器将向主服务器发送SYNC命令,而主服务器会将包含键k1至键k10089的 RDB文件发送给从服务器,从服务器通过接收和载入这个RDB文件来将自己的数据库更新至 主服务器数据库当前所处的状态
  • 为什么网络断开之后重新复制效率低,以上面的演示案例为例:
    • 主从服务器在时间T0至时间T10086中一直处于一致状态,这两个服务器保存的数据大部分都是相同的
    • 从服务器想要将自己更新至主服务器当前所处的状态,真正需要的是主从服务器连接中断期间,主服务器新添加的k10087、k10088、k10089三个键的数据
    • 可惜的是,旧版复制功能并没有利用以上列举的两点条件,而是继续让主服务器生成并向从服务器发送包含键k1至键k10089的RDB文件,但实际上RDB文件包含的键k1至键k10086的数据对于从服务器来说都是不必要的
  • 上面给出的例子可能有一点理想化,因为在主从服务器断线期间,主服务器执行的写命令可能会有成百上千个之多,而不仅仅是两三个写命令。但总的来说,主从服务器断开的时 间越短,主服务器在断线期间执行的写命令就越少,而执行少量写命令所产生的数据量通常比整个数据库的数据量要少得多,在这种情况下,为了让从服务器补足一小部分缺失的数 据,却要让主从服务器重新执行一次SYNC命令,这种做法无疑是非常低效的

Redis(设计与实现):37---复制之旧版复制功能(Redis 2.8版本之前、SYNC命令)_第5张图片

你可能感兴趣的:(Redis(设计与实现))