主从同步

同步流程

当我们启动多个 Redis 实例的时候,它们相互之间就可以通过 replicaof(Redis 5.0 之前使用 slaveof)命令形成主库和从库的关系,之后会按照三个阶段完成数据的第一次同步。

  1. 第一阶段:是主从库间建立连接、协商同步的过程,主要是为全量复制做准备。(从库给主库发送 psync 命令,表示要进行数据同步,主库根据这个命令的参数来启动复制。psync 命令包含了主库的 runID复制进度 offset 两个参数。)
  2. 在第二阶段:主库将所有数据同步给从库。从库收到数据后,在本地完成数据加载。这个过程依赖于内存快照生成的 RDB 文件。(从库接收到 RDB 文件后,会先清空当前数据库,然后加载 RDB 文件)
  3. 第三个阶段:主库会把第二阶段执行过程中新收到的写命令,再发送给从库。
image-20230417160818398

存在问题

问题一:

一次全量复制中,对于主库来说,需要完成两个耗时的操作:生成 RDB 文件和传输 RDB 文件。如果从库数量很多,而且都要和主库进行全量复制的话,就会导致主库忙于 fork 子进程生成 RDB 文件,进行数据全量同步,导致fork操作阻塞主线程

解决:通过“主 - 从 - 从”模式将主库生成 RDB 和传输 RDB 的压力,以级联的方式分散到从库上。

问题二:

网络断连或阻塞,如果从库和主库重新进行一次全量复制,开销非常大。

解决:增量复制

当主从库断连后,主库会把断连期间收到的写操作命令,写入 replication buffer,同时也会把这些操作命令也写入repl_backlog_buffer 这个缓冲区(repl_backlog_buffer 是一个环形缓冲区(所以如果长时间不恢复或者读取速度太慢了,就会被新数据覆盖导致主从库间的数据不一致。),主库会记录自己写到的位置,从库则会记录自己已经读到的位置。)。

主从库的连接恢复之后,从库首先会给主库发送 psync 命令,并把自己当前的 slave_repl_offset 发给主库,主库会判断自己的master_repl_offset 和 slave_repl_offset 之间的差距。并将中间语句同步给从库。