Redis 底层学习-多机数据库

复制

旧版复制

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

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

同步

当客户端向从服务器发送 slaveeof 命令,要求从服务器复制主服务器是,从服务器先执行同步操作。

从服务器对主服务器的同步操作需要通过向主服务器发送 sync 命令来完成,以下是 sync 命令的执行步骤:

  1. 从服务器向主服务器发送 sync 命令。

  2. 收到 sync 命令的主服务器执行 bgsave 命令,在后台生成一个 RDB 文件,并使用一个缓冲区记录从现在开始执行的所有写命令

  3. 当主服务器的 bgsave 命令执行完毕时,主服务器会将 bgsave 命令生成的 rdb 文件发送到服务器,从服务器接受并载入这个 RDB 文件,将自己的数据库状态更新至主服务器执行 bgsave 命令时的数据库状态。

  4. 主服务器将记录在缓冲区里面的所有写命令发送给从服务器,从服务器执行这些写命令,将自己的数据库状态更新至主服务器数据库当前所处的状态。

    image-20200901193329687

命令传播

主服务器会将自己执行的写命令,也即是造成主从服务器不一致的那条写命令,发送给从服务器执行,当从服务器执行了相同的写命令之后,主从服务器再次回到一致状态。

旧版复制功能的缺陷

在 Redis 中,从服务器对主服务器的复制可以分为以下两种情况:

  • 初始复制:从服务器以前没有复制过任何主服务器,或者从服务器当前要复制的主服务器和上一次复制的主服务器不同。
  • 断线后重复制:处于命令传播阶段的主从服务器因为网络原因而中断了复制,但从服务器通过自动重连重新连上了主服务器,并继续复制主服务器。

断线之后的 sync 操作,会被判定为重头开始复制,主服务器又重新生成 Rdb 文件,这样效率太差。

新版复制

为了解决旧版复制功能在处理断线重复复制时的低效问题 ,Redis 从 2.8 版本开始, 使用 psync 命令来代替 sync 来执行复制时的同步操作。

psync 命令具有完整重同步和部分重同步两种模式:

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

部分重同步的实现

部分重同步功能有以下 3 个部分组成:

  • 主服务器的复制偏移量和从服务器的复制偏移量:当前的同步进度
  • 主服务器的复制挤压缓冲区:主服务器维护的一个固定长度的(fixed-size)先进先出(fifo)队列,默认大小是 1mb
  • 服务器运行的 id:确定服务器唯一标示,在切换主从中用来区别上一次同步机器。

完整重同步和部分重同步的情况:

image-20200902101909246

新版复制流程

  1. 设置主服务器的地址和端口
  2. 建立套接字连接
  3. 发送 PING 命令:虽然主从服务器建立了套接字连接,但是未进行通信,通过发送 ping 命令,主服务器回送 pong 命令。来判断网络通信、读写是否正常。
  4. 身份验证:从服务器是否开启 masterauth 选项,主服务器是否开启了 requirepass 选项,密码是否一致。
  5. 发送从服务器端口信息
  6. 同步:完整重同步或者部分重同步操作。
  7. 命令传播:命令传播阶段,从服务器会以每秒一次的频率,向主服务器发送心跳检测。