redis 主从复制

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

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

Redis的同步包括全量同步和部分同步

全量同步

流程如下:

  1. Slave发出一个同步命令,要求Master同步数据;
  2. Master向Salve发送runid和offset;当Slave上没有offset记录时,执行全量复制;
  3. Slave执行save masterinfo,保存Master的基本信息;
  4. Master执行bgsave生成快照;
  5. Master执行send RDB将快照发送到Slave的缓冲区;
  6. Slave更新旧的RDB文件,并加载新的RDB;

由上述流程可以看到,全量同步的开销主要在:

  1. 生成RDB文件,即bgsave;
  2. RDB服务器间传输;
  3. 如果有AOF设置,达到重写阈值,会进行AOF重写;

部分同步

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

  • 主服务器的复制偏移量(replication offset)和从服务器的复制偏移量;
  • 主服务器的复制积压缓冲区(replication backlog);
  • 服务器的运行ID(run ID)。

流程如下:

  1. 存储复制信息

  redis在关闭时,通过shutdown save,都会调用rdbSaveInfoAuxFields函数,把当前实例的repl-id和repl-offset保存到RDB文件中,当前的RDB存储的数据内容和复制信息是一致性的可通过redis-check-rdb命令查看。

  2. 重启后加载RDB文件中的复制信息

  redis加载RDB文件,会专门处理文件中辅助字段(AUX fields)信息,把其中repl_id和repl_offset加载到实例中,分别赋给master_replid和master_repl_offset两个变量值,特别注意当从库开启了AOF持久化,redis加载顺序发生变化优先加载AOF文件,但是由于aof文件中没有复制信息,所以导致重启后从实例依旧使用全量复制!

  3. 向主库上报复制信息,判断是否进行部分同步

  从实例向主库上报master_replid和master_repl_offset+1;从实例同时满足以下两条件,就可以部分重新同步,否则执行全量同步:

  • 从实例上报master_replid串,与主实例的master_replid1或replid2有一个相等,用于判断主从未发生改变;
  • 从实例上报的master_repl_offset+1字节,还存在于主实例的复制积压缓冲区中,用于判断从库丢失部分是否在复制缓冲区中;

命令传播
在执行完同步操作之后,主从服务器之间数据库状态已经相同了。但这个状态并非一成不变,如果主服务器执行了写操作,那么主服务器的数据库状态就会修改,并导致主从服务器状态不再一致。

所以为了让主从服务器再次回到一致状态,主服务器需要对从服务器执行命令传播操作:主服务器会将自己执行的写命令,也即是造成主从服务器不一致的那条写命令,发送给从服务器执行,当从服务器执行了相同的写命令之后,主从服务器将再次回到一致状态。

 

posted @ 2020-04-05 17:45  薄雾2000  阅读(152)  评论(0编辑  收藏  举报