数据库
首页 > 数据库> > 《Redis设计与实现》学习笔记

《Redis设计与实现》学习笔记

作者:互联网

目录

多机数据库的实现 - 复制

通过SLAVEOF命令或者设置slaveof选项,让一个服务器(从服务器)去复制另一个服务器(主服务器),达到“数据库状态一致”效果。

旧版复制(Redis 2.8版本之前)

功能实现

同步(sync)

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

命令传播(command propagate)

同步后主服务器数据库被修改,为了让主从服务器保持一致状态,主服务器将自己执行的写命令发送给从服务器执行相同的写命令。

缺陷

复制可分为初次复制断线后重复制

断线后重复制每次都需要执行一次SYNC命令,重新复制所有的数据库数据,非常低效。

新版复制

区别

Redis从2.8版本开始,使用PSYNC命令代替SYNC命令来执行复制时的同步问题。

PSYNC命令

PSYNC命令具有完整重同步部分重同步两种模式

完整重同步

用于处理初次复制情况,和SYNC初次复制基本一致。

部分重同步

用于处理断线后重复制情况,从服务器断线重连后,在一定条件下,主服务器可以将断开期间执行的写命令发送给从服务器。

部分重同步的实现

部分重同步功能由以下三个部分构成:

1. 复制偏移量

主服务器每次向从服务器传播N个字节数据,就将自己的复制偏移量的值加上N;

从服务器每次接收主服务器传播来的N个字节数据,就将自己的复制偏移量的值加N。

通过对比主从服务器的偏移量就可以判断主从服务器是否处于一致状态

2. 复制积压缓冲区

复制积压缓冲区是由主服务器维护的一个固定长度(fixed_size)先进先出(FIFO)队列,默认大小为1MB。

主服务器在进行命令传播时,不仅会将写命令发送给从服务器,还会将写命令入队到复制积压缓冲区,复制积压缓冲区会为队列中的每个字节记录相应的复制偏移量。

从服务器断开重连后会通过PSYNC命令将自己的复制偏移量offset发送给主服务器,主服务器根据这个复制偏移量决定执行何种同步操作。

  1. offset偏移量之后的数据仍存在于复制积压缓冲区,则执行部分重同步;

  2. offset偏移量之后的数据不存在于复制积压缓冲区,则执行完整重同步。

复制积压缓冲区的大小可以根据公式second * write_size_per_second来估算

​ secoond为从服务器断线重连所需的平均时间(以秒计算)

​ write_size_per_second为主服务器平均每秒产生的写命令数据量

一般修改配置文件中repl-backlog-size选项将复制积压缓冲区大小设为

2 * second * write_size_per_second

3. 服务器运行ID

每个Redis服务器有自己的运行ID,运行ID在服务器启动时自动生成,由40个随机的十六进制字符组成。

从服务器对主服务器进行初次复制时,主服务器会将自己的运行ID传送给从服务器,从服务器会将这个运行ID保存起来。

当从服务器断线重连上一个主服务器时,从服务器会向当前连接的主服务器发送之前保存的运行ID。

  1. 从服务器保存的运行ID和当前连接的主服务器运行ID相同,则主服务器会尝试部分重同步操作;
  2. 从服务器保存的运行ID和当前连接的主服务器运行ID不相同,则主服务器执行完整同步操作。

PSYNC命令的实现

从服务器:

  1. 如果从服务器没有复制过任何主服务器或者执行过SLAVEOF no one命 令,则从服务器向主服务器发送PSYNC ? -1命令。请求完整重同步。

  2. 如果从服务器复制过某个主服务器,则从服务器向主服务器发送

    PSYNC <runid> <offset>命令,主服务器根据两个参数判断执行哪种同步操作。

主服务器:

  1. 主服务器返回+FULLRESYNC <runid> <offset>回复,表示执行完整重同步操作,其中runidoffset分别是主服务器的运行ID和复制偏移量,用于初始化从服务器。
  2. 主服务器返回+CONTINUE回复,表示执行部分重同步。
  3. 主服务器返回+ERR回复,表示主服务器版本低于Redis 2.8,识别不了PSYNC命令,从服务器会向主服务器发送SYNC命令,执行完整重同步。A

image-20210102100546085

复制的实现 (七步骤)

  1. 设置主服务器的地址和端口

通过SLAVEOF <master_ip> <master_port>,设置主从服务器

从服务器将主服务器的IP地址及端口保存到服务器状态的masterhost属性和masterport属性。

  1. 建立套接字连接

从服务器根据命令中的IP地址和端口,创建连向主服务器的套接字连接

如果成功连接,从服务器为该套接字关联一个专门用于处理复制工作的文件事件处理器,如接受RDB文件,接受主服务器传来的写命令等。

如果接受连接,主服务器为该套接字创建相应的客户端状态,这时候从服务器同时具有服务器和客户端两个身份。

  1. 发送PING命令

从服务器成为主服务器的客户端之后,第一件事就是发送一个PING命令。

PING命令的作用:

  1. 检查套接字的读写状态是否正常
  2. 检查主服务器能否正常处理命令请求,为后续步骤做检查

PING命令返回情况:

  1. 主服务器返回了一个命令回复,但从服务器不能在规定时限(timeout)内读取出命令回复内容,表示主从服务器之间的网络连接状态不佳,无法继续执行后续步骤。

    (从服务器断开并重新创建连向主服务器的套接字)

  2. 主服务器返回了一个错误,表示主服务器暂时没法处理从服务器的命令请求,无法继续执行后续步骤。

    (从服务器断开并重新创建连向主服务器的套接字)

  3. 从服务器读取到“pong”回复,表示主从服务器之间的网络连接状态正常,主服务器能正常处理命令请求,可以继续执行后续步骤。

image-20210102103303488

  1. 身份验证

根据从服务器是否设置了masterauth选项,决定是否进行身份验证。

设置了masterauth:

从服务器向主服务器发送一条AUTH命令,命令参数为从服务器masterauth选项的值

身份验证的三种情况:

  1. 主服务器没有设置requirepass选项,从服务器也没有设置masterauth选项,主服务器继续执行从服务器发送的命令,复制工作继续进行。

  2. 从服务器通过AUTH命令发送的密码和主服务器requirepass选项设置的密码相同,主服务器继续执行从服务器发送的命令,复制工作继续进行。如果不相同,主服务器返回一个invalid password错误。

  3. 如果主服务器设置了requirepass选项,从服务器没有设置masterauth选项,主服务器返回一个NOAUTH错误;

    如果主服务器没有设置requirepass选项,从服务器设置了masterauth选项,主服务器返回一个no password is set错误。

image-20210102104649970

  1. 发送端口信息

从服务器执行命令REPLCONF listening-port <port-number>,向主服务器发送从服务器的监听端口号。

主服务器将端口号记录在从服务器对应的客户端状态的slave_listening_port属性中,该属性目前唯一的作用是在主服务器执行INFO replication命令时打印从服务器的端口号。

  1. 同步

从服务器向主服务器发送PSYNC命令,执行同步操作

执行同步操作前,只有从服务器是主服务器的客户端,执行同步操作后,主从服务器互为对方的客户端

(只有成为客户端,才可以互相向对方发送命令请求或者返回命令回复)

  1. 命令传播

主服务器一直将执行的写命令发送给从服务器,从服务器一直接收并执行主服务器发来的写命令,保持主从一致。

心跳检测

命令传播阶段,从服务器每秒一次向主服务器发送命令:

REPLCONF ACK <replication_offset>,其中replication_offset为从服务器当前的复制偏移量。

REPLCONF ACK命令的作用

主服务器超过一秒钟没有收到从服务器发来的REPLCONF ACK命令,则说明主从服务器之间的连接出现问题。

可以通过INFO replication命令,在服务器列表的lag属性查看从服务器上一次发送REPLCONF ACK距离现在的时间。(一般在0~1秒之间跳动)

Redis中的min-slaves-to-writemin-slaves-max-lag可以防止主服务器在不安全的情况下执行写命令,这里的min-slaves-max-lag就是上面提到的读取的lag值。

从服务器在发送REPLCONF ACK命令时发送复制偏移量,如果因为网络故障发生命令丢失,主从服务器复制偏移量不同,主服务器会根据从服务器提交的复制偏移量,在复制积压缓冲区找到丢失的数据重新发送。

(不同于部分重同步,区别是有没有断线)

标签:Redis,笔记,学习,命令,复制,偏移量,服务器发送,服务器,ID
来源: https://www.cnblogs.com/Zzzkis/p/14221865.html