(七)、主重复制---Redis设计与实现读书笔记

版权声明:Author:我爱双面奶 https://blog.csdn.net/qq_34092585/article/details/82822308

1、概述

一个服务器去复制另一个服务器,被复制服务器为主服务器(master)、对主服务器进行复制的服务器为从服务器(slave)

image

命令:

SLAVEOF “主服务器IP” “主服务器端口号”

2、2.8之前版本主从复制实现

Redis的主从复制功能分为"同步"和"命令传播"

  1. 用户向从服务器发送SLAVEOF命令时,从服务器对主服务器执行同步操作,主从服务器数据达到一致性状态

  2. 主服务器更新数据后,主从服务器数据会再次不一致,主服务器对从服务器执行**命令传播**,主从服务器再次进入一致性状态。

2.1、同步实现步骤

  1. 从服务器向主服务器发送SYNC命令
  2. 主服务器收到SYNC命令后执行BGSAVE命令,通过子进程生成RDB文件,并使用缓冲区记录从现在开始的所有写命令
  3. 主服务器将RDB文件通过网络发送给从服务器
  4. 从服务器接收并载入RDB文件,此时从服务器数据和主服务器执行BGSAVE命令时的状态一致
  5. 主服务器将缓冲区里的所有写命令发送给从服务器
  6. 从服务器执行这些写命令,此时主从服务器数据一致。

2.2、命令传播

主服务器将造成主从服务器不一致的那条写命令,发送给从服务器执行,主从服务器再次进入一致状态。

2.3、2.8之前版本主从复制的缺陷

复制分为以下两种情况:

初次复制:从服务器第一次主从复制。

断线后复制:处于"命令传播"阶段的主从服务器因为网络原因中断复制,之后网络恢复后,从服务器重新连接上主服务器,执行主从复制。

在2.8执行版本Redis中,这两种情况都是使用BGSAVE的方式生成RDB文件来实现主从复制,但是在"断线后复制"这种情况下,主从服务器只有在断线后那一部分数据是不一致的,通过RDB的方式恢复了很多重复的数据,这非常低效。

3、 SYNC命令实现

SYNC命令是非常消耗资源的,因为每次执行SYNC命令,主从服务器需要执行一下操作:

  1. 主服务器需要执行BGSAVE命令来生成RDB文件,这个生成操作会耗费主服务器大量的CPU、内存和磁盘I/O资源;
  2. 主服务器需要将自己生成的RDB文件发送给从服务器,这个发送操作会耗费主从服务器大量的网络资源(带宽和流量),并对主服务器响应命令请求的时间产生影响;
  3. 接收到RDB文件的从服务器需要载入主服务器发来的RDB文件,并且在载入期间,从服务器会因为阻塞而没办法处理命令请求。

因为SYNC命令耗费大量资源,所以只能在必要的时候使用,所以Redis在2.8以后的版本,对主从复制使用部分重同步进行了改进

4、2.8以后版本主从复制实现

为解决主从复制在断线后重复复制的低效问题,使用PSYNC命令代替之前的SYNC命令来完成同步操作。

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

完整重同步:用于初次复制的情况,执行步骤和SYNC命令的执行步骤基本一样。

部分重同步:用于断线后重新复制的情况,比SYNC命令所需要的资源少,且速度快,因为相对于载入RDB文件,部分重同步只需要将从服务器缺少的写命令发送给从服务器就行

4.1、部分重同步实现

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

  1. 主服务的复制偏移量:通过偏移量判断是否处于一致状态。
  2. 主服务器的复制积压缓存区:由主服务器维护的一个固定长度、先进先出队列,默认是1MB,可配置文件修改。
  3. 服务器的运行id:标识服务器,在服务器启动时生成,由40个随机的十六进制字符组成。

当偏移量之后的数据仍然存在复制积压缓冲区中,那么主服务器将对从服务器执行部分重同步操作。反之将主服务器执行完整重同步操作

4.2、PSYNC命令实现

PSYNC命令的调用方法有两种:

  • 如果从服务器以前没有复制过任何主服务器,或者之前执行过SLAVEOF no one命令,那么从服务器在开始一次新的复制时将向主服务器发送PSYNC ? -1命令,主动请求主服务器进行完整重同步(因为这时不可能执行部分重同步);

  • 相反地,如果从服务器已经复制过某个主服务器,那么从服务器在开始一次新的复制时将向主服务器发送PSYNC <runid> <offset>命令:其中runid是上一次复制的主服务器的运行ID,而offset则是从服务器当前的复制偏移量,接收到这个命令的主服务器会通过这两个参数来判断应该对从服务器执行哪种同步操作。

根据情况,接收到PSYNC命令的主服务器会向从服务器返回以下三种回复的其中一种:

  • 如果主服务器返回+FULLRESYNC <runid> <offset>回复,那么表示主服务器将与从服务器执行完整重同步操作:其中runid是这个主服务器的运行ID,从服务器会将这个ID保存起来,在下一次发送PSYNC命令时使用;而offset则是主服务器当前的复制偏移量,从服务器会将这个值作为自己的初始化偏移量;
  • 如果主服务器返回+CONTINUE回复,那么表示主服务器将与从服务器执行部分重同步操作,从服务器只要等着主服务器将自己缺少的那部分数据发送过来就可以了;
  • 如果主服务器返回-ERR回复,那么表示主服务器的版本低于Redis 2.8,它识别不了PSYNC命令,从服务器将向主服务器发送SYNC命令,并与主服务器执行完整同步操作。

image

5、复制实现步骤

  1. 设置主服务器的地址和端口
  2. 建立套接字连接(TCP)
  3. 发送PING命令
  4. 身份验证
  5. 发送端口信息
  6. 同步
  7. 命令传播

猜你喜欢

转载自blog.csdn.net/qq_34092585/article/details/82822308